Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #90858

Closed
wants to merge 11 commits into from
Closed
60 changes: 38 additions & 22 deletions compiler/rustc_borrowck/src/type_check/input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).

use crate::type_check::constraint_conversion::ConstraintConversion;
use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty::Ty;
use rustc_span::Span;
use rustc_trait_selection::traits::query::normalize::AtExt;
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use rustc_trait_selection::traits::query::Fallible;
use type_op::TypeOpOutput;

use crate::universal_regions::UniversalRegions;

Expand All @@ -30,6 +33,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let (&normalized_output_ty, normalized_input_tys) =
normalized_inputs_and_output.split_last().unwrap();

debug!(?normalized_output_ty);
debug!(?normalized_input_tys);

let mir_def_id = body.source.def_id().expect_local();

// If the user explicitly annotated the input types, extract
Expand Down Expand Up @@ -75,10 +81,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
break;
}

// In MIR, argument N is stored in local N+1.
let local = Local::new(argument_index + 1);

let mir_input_ty = body.local_decls[local].ty;

let mir_input_span = body.local_decls[local].source_info.span;
self.equate_normalized_input_or_output(
normalized_input_ty,
Expand All @@ -100,6 +108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// If the user explicitly annotated the input types, enforce those.
let user_provided_input_ty =
self.normalize(user_provided_input_ty, Locations::All(mir_input_span));

self.equate_normalized_input_or_output(
user_provided_input_ty,
mir_input_ty,
Expand Down Expand Up @@ -167,30 +176,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
// like to normalize *before* inserting into `local_decls`, but
// doing so ends up causing some other trouble.
let b = match self
.infcx
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
.normalize(b)
{
Ok(n) => {
debug!("equate_inputs_and_outputs: {:?}", n);
if n.obligations.iter().all(|o| {
matches!(
o.predicate.kind().skip_binder(),
ty::PredicateKind::RegionOutlives(_)
| ty::PredicateKind::TypeOutlives(_)
)
}) {
n.value
} else {
b
}
}
let b = match self.normalize_and_add_constraints(b) {
Ok(n) => n,
Err(_) => {
debug!("equate_inputs_and_outputs: NoSolution");
b
}
};

// Note: if we have to introduce new placeholders during normalization above, then we won't have
// added those universes to the universe info, which we would want in `relate_tys`.
if let Err(terr) =
Expand All @@ -207,4 +200,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
}

pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
let TypeOpOutput { output: norm_ty, constraints, .. } =
self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;

debug!("{:?} normalized to {:?}", t, norm_ty);

for data in constraints.into_iter().collect::<Vec<_>>() {
ConstraintConversion::new(
self.infcx,
&self.borrowck_context.universal_regions,
&self.region_bound_pairs,
Some(self.implicit_region_bound),
self.param_env,
Locations::All(DUMMY_SP),
ConstraintCategory::Internal,
&mut self.borrowck_context.constraints,
)
.convert_all(&*data);
}

Ok(norm_ty)
}
}
5 changes: 3 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,11 +893,11 @@ struct TypeChecker<'a, 'tcx> {
}

struct BorrowCheckContext<'a, 'tcx> {
universal_regions: &'a UniversalRegions<'tcx>,
pub(crate) universal_regions: &'a UniversalRegions<'tcx>,
location_table: &'a LocationTable,
all_facts: &'a mut Option<AllFacts>,
borrow_set: &'a BorrowSet<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
upvars: &'a [Upvar<'tcx>],
}

Expand Down Expand Up @@ -1157,6 +1157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
}

#[instrument(skip(self, category), level = "debug")]
fn eq_types(
&mut self,
expected: Ty<'tcx>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
new_ty.to_string(),
Applicability::Unspecified,
);
} else {
diag.span_label(
new_ty_span,
&format!("{} does not have lifetime `'static'`", span_label_var),
);
}

Some(diag)
Expand Down
32 changes: 32 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ impl CheckAttrVisitor<'tcx> {
self.check_default_method_body_is_const(attr, span, target)
}
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
sym::rustc_const_unstable
| sym::rustc_const_stable
| sym::unstable
Expand Down Expand Up @@ -1046,6 +1047,37 @@ impl CheckAttrVisitor<'tcx> {
is_valid
}

/// Warns against some misuses of `#[must_use]`
fn check_must_use(
&self,
hir_id: HirId,
attr: &Attribute,
span: &Span,
_target: Target,
) -> bool {
let node = self.tcx.hir().get(hir_id);
if let Some(fn_node) = node.fn_kind() {
if let rustc_hir::IsAsync::Async = fn_node.asyncness() {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build(
"`must_use` attribute on `async` functions \
applies to the anonymous `Future` returned by the \
function, not the value within.",
)
.span_label(
*span,
"this attribute does nothing, the `Future`s \
returned by async functions are already `must_use`",
)
.emit();
});
}
}

// For now, its always valid
true
}

/// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid.
fn check_must_not_suspend(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
match target {
Expand Down
4 changes: 0 additions & 4 deletions src/librustdoc/html/render/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,13 +398,9 @@ crate fn get_all_types<'tcx>(
if arg.type_.is_self_type() {
continue;
}
// FIXME: performance wise, it'd be much better to move `args` declaration outside of the
// loop and replace this line with `args.clear()`.
let mut args = Vec::new();
get_real_types(generics, &arg.type_, tcx, 0, &mut args);
if !args.is_empty() {
// FIXME: once back to performance improvements, replace this line with:
// `all_types.extend(args.drain(..));`.
all_types.extend(args);
} else {
if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Check to see if we can get parameters from an @argsfile file
//
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile-badutf8.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// normalize-stderr-test: "os error \d+" -> "os error $$ERR"
// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile-missing.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Check to see if we can get parameters from an @argsfile file
//
// check-pass
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile/commandline-argfile.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5
|
LL | fn foo(x: &()) {
| --- the type of `x` does not have lifetime `'static'`
LL | bar(|| {
| ^^^ lifetime `'static` required

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Check to see if we can get parameters from an @argsfile file
//
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
// compile-flags: --cfg cmdline_set @{{src-base}}/command/argfile/commandline-argfile-badutf8.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// normalize-stderr-test: "os error \d+" -> "os error $$ERR"
// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
// compile-flags: --cfg cmdline_set @{{src-base}}/command/argfile/commandline-argfile-missing.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Check to see if we can get parameters from an @argsfile file
//
// build-pass
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args
// compile-flags: --cfg cmdline_set @{{src-base}}/command/argfile/commandline-argfile.args

#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/generator/generator-region-requirements.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/generator-region-requirements.rs:12:51
|
LL | fn dangle(x: &mut i32) -> &'static mut i32 {
| -------- the type of `x` does not have lifetime `'static'`
...
LL | GeneratorState::Complete(c) => return c,
| ^ lifetime `'static` required

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/projection-type-lifetime-mismatch.rs:17:5
|
LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
| ------------------------------- the type of `x` does not have lifetime `'static'`
LL | x.m()
| ^^^^^ lifetime `'static` required

error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/projection-type-lifetime-mismatch.rs:22:5
|
LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
| -- the type of `x` does not have lifetime `'static'`
LL | x.m()
| ^^^^^ lifetime `'static` required

error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/projection-type-lifetime-mismatch.rs:27:5
|
LL | fn h(x: &()) -> &'static () {
| --- the type of `x` does not have lifetime `'static'`
LL | x.m()
| ^^^^^ lifetime `'static` required

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// check-pass

#![feature(generic_associated_types)]

use std::marker::PhantomData;

trait Family: Sized {
type Item<'a>;

fn apply_all<F>(&self, f: F)
where
F: FamilyItemFn<Self> { }
}

struct Array<T>(PhantomData<T>);

impl<T: 'static> Family for Array<T> {
type Item<'a> = &'a T;
}

trait FamilyItemFn<T: Family> {
fn apply(&self, item: T::Item<'_>);
}

impl<T, F> FamilyItemFn<T> for F
where
T: Family,
for<'a> F: Fn(T::Item<'a>)
{
fn apply(&self, item: T::Item<'_>) {
(*self)(item);
}
}

fn process<T: 'static>(array: Array<T>) {
// Works
array.apply_all(|x: &T| { });

// ICE: NoSolution
array.apply_all(|x: <Array<T> as Family>::Item<'_>| { });
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//check-pass

#![feature(generic_associated_types)]

trait Yokeable<'a>: 'static {
type Output: 'a;
}

trait IsCovariant<'a> {}

struct Yoke<Y: for<'a> Yokeable<'a>> {
data: Y,
}

impl<Y: for<'a> Yokeable<'a>> Yoke<Y> {
fn project<Y2: for<'a> Yokeable<'a>>(&self, _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ())
-> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> {

unimplemented!()
}
}

fn _upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where
Y: for<'a> Yokeable<'a>,
for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a>
{
x.project(|data, _| {
Box::new(data)
})
}


impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> {
type Output = Box<dyn IsCovariant<'a> + 'a>;
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/issue-46983.rs:2:5
--> $DIR/issue-46983-expected-return-static.rs:2:5
|
LL | fn foo(x: &u32) -> &'static u32 {
| ---- the type of `x` does not have lifetime `'static'`
LL | &*x
| ^^^ lifetime `'static` required

Expand Down
Loading