From be5a45d39240ab3f6410c4808b0840142c657228 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Mon, 31 Oct 2022 11:45:11 +0300 Subject: [PATCH] fix struct path --- Cargo.lock | 1 + compiler/rustc_hir_typeck/Cargo.toml | 1 + .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 38 ++++++--- src/test/ui/const-generics/issue-97007.rs | 6 +- .../user-annotations/dump-adt-brace-struct.rs | 2 - .../dump-adt-brace-struct.stderr | 18 +--- .../nll/user-annotations/normalization-2.rs | 36 +++++++- .../user-annotations/normalization-2.stderr | 83 +++++++++++++++---- 8 files changed, 137 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f48506b5af..fd55c121bc4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4134,6 +4134,7 @@ dependencies = [ name = "rustc_hir_typeck" version = "0.1.0" dependencies = [ + "either", "rustc_ast", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 093f9bb8448..114b2d37fb8 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" +either = "1.5.0" rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 6a822568775..92a0b9785d0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -32,6 +32,8 @@ use rustc_span::symbol::{kw, Ident}; use rustc_span::{self, sym, Span}; use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}; +use either::Either; + use std::iter; use std::mem; use std::ops::ControlFlow; @@ -1231,28 +1233,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); return None; } - Res::Def(DefKind::Variant, _) => match ty.normalized.kind() { - ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)), + Res::Def(DefKind::Variant, _) => match (ty.raw.kind(), ty.normalized.kind()) { + (ty::Adt(adt, substs), _) => { + Some((adt.variant_of_res(def), adt.did(), substs, Either::Left(substs))) + } + (_, ty::Adt(adt, substs)) => { + Some((adt.variant_of_res(def), adt.did(), substs, Either::Right(ty.raw))) + } _ => bug!("unexpected type: {:?}", ty.normalized), }, Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) | Res::SelfTyParam { .. } - | Res::SelfTyAlias { .. } => match ty.normalized.kind() { - ty::Adt(adt, substs) if !adt.is_enum() => { - Some((adt.non_enum_variant(), adt.did(), substs)) + | Res::SelfTyAlias { .. } => match (ty.raw.kind(), ty.normalized.kind()) { + (ty::Adt(adt, substs), _) if !adt.is_enum() => { + Some((adt.non_enum_variant(), adt.did(), substs, Either::Left(substs))) + } + (_, ty::Adt(adt, substs)) if !adt.is_enum() => { + Some((adt.non_enum_variant(), adt.did(), substs, Either::Right(ty.raw))) } _ => None, }, _ => bug!("unexpected definition: {:?}", def), }; - if let Some((variant, did, substs)) = variant { + if let Some((variant, did, substs, user_annotation)) = variant { debug!("check_struct_path: did={:?} substs={:?}", did, substs); - // FIXME(aliemjay): We're using UserSelfTy unconditionally here because it is the only - // way to register the raw user ty, because `substs` is normalized. - let self_ty = ty::UserSelfTy { impl_def_id: did, self_ty: ty.raw }; - self.write_user_type_annotation_from_substs(hir_id, did, substs, Some(self_ty)); + // Register type annotation. + self.probe(|_| { + // UserSubsts and UserSelfTy are mutually exclusive here. + let (user_substs, self_ty) = match user_annotation { + Either::Left(substs) => (*substs, None), + Either::Right(self_ty) => { + (self.fresh_substs_for_item(path_span, did), Some(self_ty)) + } + }; + let self_ty = self_ty.map(|self_ty| ty::UserSelfTy { impl_def_id: did, self_ty }); + self.write_user_type_annotation_from_substs(hir_id, did, user_substs, self_ty); + }); // Check bounds on type arguments used in the path. self.add_required_obligations_for_hir(path_span, did, substs, hir_id); diff --git a/src/test/ui/const-generics/issue-97007.rs b/src/test/ui/const-generics/issue-97007.rs index 7b9b9701ff1..7036834c4b1 100644 --- a/src/test/ui/const-generics/issue-97007.rs +++ b/src/test/ui/const-generics/issue-97007.rs @@ -1,8 +1,4 @@ -//~ ERROR broken MIR - -// known-bug -// failure-status: 101 -// rustc-env: RUSTC_BACKTRACE=0 +// check-pass #![feature(adt_const_params, generic_const_exprs)] #![allow(incomplete_features)] diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs index 8a80958fc67..ccda9129dab 100644 --- a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs +++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs @@ -11,10 +11,8 @@ struct SomeStruct { t: T } #[rustc_dump_user_substs] fn main() { SomeStruct { t: 22 }; // Nothing given, no annotation. - //~^ ERROR SomeStruct<^0> SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation. - //~^ ERROR SomeStruct<^0> SomeStruct:: { t: 22 }; // No lifetime bounds given. diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr index b5adc584b28..5860621909c 100644 --- a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr +++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr @@ -1,20 +1,8 @@ -error: user substs: UserSubsts { substs: [^0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<^0> }) } - --> $DIR/dump-adt-brace-struct.rs:13:5 - | -LL | SomeStruct { t: 22 }; // Nothing given, no annotation. - | ^^^^^^^^^^^^^^^^^^^^ - -error: user substs: UserSubsts { substs: [^0], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<^0> }) } - --> $DIR/dump-adt-brace-struct.rs:16:5 - | -LL | SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation. - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: Some(UserSelfTy { impl_def_id: DefId(0:3 ~ dump_adt_brace_struct[4679]::SomeStruct), self_ty: SomeStruct<&ReStatic u32> }) } - --> $DIR/dump-adt-brace-struct.rs:21:5 +error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None } + --> $DIR/dump-adt-brace-struct.rs:19:5 | LL | SomeStruct::<&'static u32> { t: &22 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to previous error diff --git a/src/test/ui/nll/user-annotations/normalization-2.rs b/src/test/ui/nll/user-annotations/normalization-2.rs index 00e9eb651cd..92600155c7f 100644 --- a/src/test/ui/nll/user-annotations/normalization-2.rs +++ b/src/test/ui/nll/user-annotations/normalization-2.rs @@ -24,6 +24,7 @@ enum MyTy { impl MyTy { fn method() {} + fn method2(&self) {} } type Ty<'a> = <&'a () as Trait>::Assoc; @@ -45,6 +46,9 @@ fn test_path<'a, 'b, 'c, 'd>() { //~^ ERROR lifetime may not live long enough >::method::>; //~^ ERROR lifetime may not live long enough + + MyTy::Unit::>; + //~^ ERROR lifetime may not live long enough } fn test_call<'a, 'b, 'c>() { @@ -55,7 +59,7 @@ fn test_call<'a, 'b, 'c>() { } fn test_variants<'a, 'b, 'c>() { - >::Struct {}; //TODO + >::Struct {}; //~^ ERROR lifetime may not live long enough >::Tuple(); //~^ ERROR lifetime may not live long enough @@ -63,6 +67,36 @@ fn test_variants<'a, 'b, 'c>() { //~^ ERROR lifetime may not live long enough } +fn test_method_call<'a>(x: MyTy<()>) { + // FIXME This should fail. + x.method2::>(); +} + +fn test_struct_path<'a, 'b, 'c, 'd>() { + struct Struct { x: Option, } + + trait Project { + type Struct; + type Enum; + } + impl Project for T { + type Struct = Struct<()>; + type Enum = MyTy<()>; + } + + // Resolves to enum variant + MyTy::>::Struct {}; // without SelfTy + //~^ ERROR lifetime may not live long enough + as Project>::Enum::Struct {}; // with SelfTy + //~^ ERROR lifetime may not live long enough + + // Resolves to struct and associated type respectively + Struct::> { x: None, }; // without SelfTy + //~^ ERROR lifetime may not live long enough + as Project>::Struct { x: None, }; // with SelfTy + //~^ ERROR lifetime may not live long enough +} + fn test_pattern<'a, 'b, 'c>() { use MyTy::*; match MyTy::Unit { diff --git a/src/test/ui/nll/user-annotations/normalization-2.stderr b/src/test/ui/nll/user-annotations/normalization-2.stderr index 3c235171ef5..5dbdb2ecea8 100644 --- a/src/test/ui/nll/user-annotations/normalization-2.stderr +++ b/src/test/ui/nll/user-annotations/normalization-2.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/normalization-2.rs:32:12 + --> $DIR/normalization-2.rs:33:12 | LL | fn test_local<'a>() { | -- lifetime `'a` defined here @@ -7,7 +7,7 @@ LL | let _: Ty<'a> = MyTy::Unit; | ^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:37:6 + --> $DIR/normalization-2.rs:38:6 | LL | fn test_closure_sig<'a, 'b>() { | -- lifetime `'a` defined here @@ -15,7 +15,7 @@ LL | |_: Ty<'a>| {}; | ^ requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:39:11 + --> $DIR/normalization-2.rs:40:11 | LL | fn test_closure_sig<'a, 'b>() { | -- lifetime `'b` defined here @@ -29,7 +29,7 @@ help: the following changes may resolve your lifetime errors = help: replace `'b` with `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:44:5 + --> $DIR/normalization-2.rs:45:5 | LL | fn test_path<'a, 'b, 'c, 'd>() { | -- lifetime `'a` defined here @@ -37,7 +37,7 @@ LL | >::method::>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:46:5 + --> $DIR/normalization-2.rs:47:5 | LL | fn test_path<'a, 'b, 'c, 'd>() { | -- lifetime `'b` defined here @@ -45,13 +45,23 @@ LL | fn test_path<'a, 'b, 'c, 'd>() { LL | >::method::>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:50:5 + | +LL | fn test_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'c` defined here +... +LL | MyTy::Unit::>; + | ^^^^^^^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` + help: the following changes may resolve your lifetime errors | = help: replace `'a` with `'static` = help: replace `'b` with `'static` + = help: replace `'c` with `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:51:5 + --> $DIR/normalization-2.rs:55:5 | LL | fn test_call<'a, 'b, 'c>() { | -- lifetime `'a` defined here @@ -59,7 +69,7 @@ LL | >::method::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:53:5 + --> $DIR/normalization-2.rs:57:5 | LL | fn test_call<'a, 'b, 'c>() { | -- lifetime `'b` defined here @@ -73,15 +83,15 @@ help: the following changes may resolve your lifetime errors = help: replace `'b` with `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:58:5 + --> $DIR/normalization-2.rs:62:5 | LL | fn test_variants<'a, 'b, 'c>() { | -- lifetime `'a` defined here -LL | >::Struct {}; //TODO +LL | >::Struct {}; | ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:60:5 + --> $DIR/normalization-2.rs:64:5 | LL | fn test_variants<'a, 'b, 'c>() { | -- lifetime `'b` defined here @@ -90,7 +100,7 @@ LL | >::Tuple(); | ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:62:5 + --> $DIR/normalization-2.rs:66:5 | LL | fn test_variants<'a, 'b, 'c>() { | -- lifetime `'c` defined here @@ -105,7 +115,50 @@ help: the following changes may resolve your lifetime errors = help: replace `'c` with `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:69:9 + --> $DIR/normalization-2.rs:88:5 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'a` defined here +... +LL | MyTy::>::Struct {}; // without SelfTy + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:90:5 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'b` defined here +... +LL | as Project>::Enum::Struct {}; // with SelfTy + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:94:5 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'c` defined here +... +LL | Struct::> { x: None, }; // without SelfTy + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:96:5 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'d` defined here +... +LL | as Project>::Struct { x: None, }; // with SelfTy + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + = help: replace `'c` with `'static` + = help: replace `'d` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:103:9 | LL | fn test_pattern<'a, 'b, 'c>() { | -- lifetime `'a` defined here @@ -114,7 +167,7 @@ LL | Struct::> {..} => {}, | ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:71:9 + --> $DIR/normalization-2.rs:105:9 | LL | fn test_pattern<'a, 'b, 'c>() { | -- lifetime `'b` defined here @@ -123,7 +176,7 @@ LL | Tuple::> (..) => {}, | ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` error: lifetime may not live long enough - --> $DIR/normalization-2.rs:73:9 + --> $DIR/normalization-2.rs:107:9 | LL | fn test_pattern<'a, 'b, 'c>() { | -- lifetime `'c` defined here @@ -137,5 +190,5 @@ help: the following changes may resolve your lifetime errors = help: replace `'b` with `'static` = help: replace `'c` with `'static` -error: aborting due to 13 previous errors +error: aborting due to 18 previous errors