From 35c03b2323ca4c594e9e3aaf35c57c1de1e0a4af Mon Sep 17 00:00:00 2001 From: jackh726 Date: Thu, 25 Nov 2021 21:16:27 -0500 Subject: [PATCH] Don't treat unnormalized function arguments as well-formed --- .../src/type_check/free_region_relations.rs | 6 ++-- .../rustc_typeck/src/check/compare_method.rs | 7 +---- compiler/rustc_typeck/src/check/mod.rs | 1 - compiler/rustc_typeck/src/check/wfcheck.rs | 5 ---- ...d-bounds-unnorm-associated-type.nll.stderr | 14 +++++++++ .../implied-bounds-unnorm-associated-type.rs | 22 ++++++++++++++ ...plied-bounds-unnorm-associated-type.stderr | 13 ++++++++ .../generic-associated-types/issue-87748.rs | 30 ------------------- 8 files changed, 52 insertions(+), 46 deletions(-) create mode 100644 src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr create mode 100644 src/test/ui/fn/implied-bounds-unnorm-associated-type.rs create mode 100644 src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr delete mode 100644 src/test/ui/generic-associated-types/issue-87748.rs diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index f71cf09ecf630..8d97c3cbb0b0e 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -256,7 +256,6 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { debug!("build: input_or_output={:?}", ty); // We add implied bounds from both the unnormalized and normalized ty // See issue #87748 - let constraints_implied_1 = self.add_implied_bounds(ty); let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) @@ -284,10 +283,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { // } // ``` // Both &Self::Bar and &() are WF - let constraints_implied_2 = - if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None }; + let constraints_implied = self.add_implied_bounds(norm_ty); normalized_inputs_and_output.push(norm_ty); - constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2) + constraints1.into_iter().chain(constraints_implied) }) .collect(); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 4d4662f73a955..fdc5d16acc144 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -264,14 +264,9 @@ fn compare_predicate_entailment<'tcx>( // First liberate late bound regions and subst placeholders let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); - // Next, add all inputs and output as well-formed tys. Importantly, - // we have to do this before normalization, since the normalized ty may - // not contain the input parameters. See issue #87748. - wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); - // Also add the resulting inputs and output as well-formed. - // This probably isn't strictly necessary. + // Add the resulting inputs and output as well-formed. wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index e7fba3a70ff42..7bfd3f0ee8047 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -391,7 +391,6 @@ fn typeck_with_fallback<'tcx>( let mut wf_tys = FxHashSet::default(); // Compute the fty from point of view of inside the fn. let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); - wf_tys.extend(fn_sig.inputs_and_output.iter()); let fn_sig = inh.normalize_associated_types_in( body.value.span, body_id.hir_id, diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 0050ac99cb19a..e58faf9a89dd4 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1322,11 +1322,6 @@ fn check_fn_or_method<'fcx, 'tcx>( ) { let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); - // Unnormalized types in signature are WF too - implied_bounds.extend(sig.inputs()); - // FIXME(#27579) return types should not be implied bounds - implied_bounds.insert(sig.output()); - // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` // on the entire `FnSig`, since this would use the same `WellFormedLoc` diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr new file mode 100644 index 0000000000000..e37ec7f26651c --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5 + | +LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | s + | ^ returning this value requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs new file mode 100644 index 0000000000000..2e5ac7d7398eb --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs @@ -0,0 +1,22 @@ +// check-fail +// See issue #91068. Types in the substs of an associated type can't be implied +// to be WF, since they don't actually have to be constructed. + +trait Trait { + type Type; +} + +impl Trait for T { + type Type = (); +} + +fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + s //~ ERROR lifetime mismatch [E0623] +} + +fn main() { + let x = String::from("Hello World!"); + let y = f(&x, ()); + drop(x); + println!("{}", y); +} diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr new file mode 100644 index 0000000000000..93ab5dceee947 --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr @@ -0,0 +1,13 @@ +error[E0623]: lifetime mismatch + --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5 + | +LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + | ------- ---------- + | | + | these two types are declared with different lifetimes... +LL | s + | ^ ...but data from `s` flows here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/generic-associated-types/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs deleted file mode 100644 index 93c3b3937cb81..0000000000000 --- a/src/test/ui/generic-associated-types/issue-87748.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Checks that we properly add implied bounds from unnormalized projections in -// inputs when typechecking functions. - -// check-pass - -#![feature(generic_associated_types)] - -trait MyTrait { - type Assoc<'a, 'b> where 'b: 'a; - fn do_sth(arg: Self::Assoc<'_, '_>); -} - -struct A; -struct B; -struct C; - -impl MyTrait for A { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: u32) {} -} -impl MyTrait for B { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: Self::Assoc<'_, '_>) {} -} -impl MyTrait for C { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: Self::Assoc<'static, 'static>) {} -} - -fn main () {}