From dedf2eda8f6d062da91c80a8980b3b794f5c876e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 16 Jun 2019 17:23:41 +0300 Subject: [PATCH] rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`. --- src/librustc_typeck/check/mod.rs | 96 +++++++++---------- .../{run-pass => ui}/issues/issue-57924.rs | 1 + src/test/ui/issues/issue-57924.stderr | 9 ++ src/test/ui/issues/issue-61882-2.rs | 11 +++ src/test/ui/issues/issue-61882-2.stderr | 15 +++ src/test/ui/issues/issue-61882.rs | 9 ++ src/test/ui/issues/issue-61882.stderr | 21 ++++ 7 files changed, 109 insertions(+), 53 deletions(-) rename src/test/{run-pass => ui}/issues/issue-57924.rs (64%) create mode 100644 src/test/ui/issues/issue-57924.stderr create mode 100644 src/test/ui/issues/issue-61882-2.rs create mode 100644 src/test/ui/issues/issue-61882-2.stderr create mode 100644 src/test/ui/issues/issue-61882.rs create mode 100644 src/test/ui/issues/issue-61882.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 22f17097fcb..a5d9284a6fe 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5300,52 +5300,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(original_span.with_lo(original_span.hi() - BytePos(1))) } - // Rewrite `SelfCtor` to `Ctor` - pub fn rewrite_self_ctor( - &self, - res: Res, - span: Span, - ) -> Result { - let tcx = self.tcx; - if let Res::SelfCtor(impl_def_id) = res { - let ty = self.impl_self_ty(span, impl_def_id).ty; - let adt_def = ty.ty_adt_def(); - - match adt_def { - Some(adt_def) if adt_def.has_ctor() => { - let variant = adt_def.non_enum_variant(); - let ctor_def_id = variant.ctor_def_id.unwrap(); - Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id)) - } - _ => { - let mut err = tcx.sess.struct_span_err(span, - "the `Self` constructor can only be used with tuple or unit structs"); - if let Some(adt_def) = adt_def { - match adt_def.adt_kind() { - AdtKind::Enum => { - err.help("did you mean to use one of the enum's variants?"); - }, - AdtKind::Struct | - AdtKind::Union => { - err.span_suggestion( - span, - "use curly brackets", - String::from("Self { /* fields */ }"), - Applicability::HasPlaceholders, - ); - } - } - } - err.emit(); - - Err(ErrorReported) - } - } - } else { - Ok(res) - } - } - // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_value_path(&self, @@ -5365,12 +5319,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; - let res = match self.rewrite_self_ctor(res, span) { - Ok(res) => res, - Err(ErrorReported) => return (tcx.types.err, res), - }; let path_segs = match res { - Res::Local(_) => vec![], + Res::Local(_) | Res::SelfCtor(_) => vec![], Res::Def(kind, def_id) => AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id), _ => bug!("instantiate_value_path on {:?}", res), @@ -5475,13 +5425,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.generics_of(*def_id).has_self }).unwrap_or(false); + let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res { + let ty = self.impl_self_ty(span, impl_def_id).ty; + let adt_def = ty.ty_adt_def(); + + match ty.sty { + ty::Adt(adt_def, substs) if adt_def.has_ctor() => { + let variant = adt_def.non_enum_variant(); + let ctor_def_id = variant.ctor_def_id.unwrap(); + ( + Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id), + Some(substs), + ) + } + _ => { + let mut err = tcx.sess.struct_span_err(span, + "the `Self` constructor can only be used with tuple or unit structs"); + if let Some(adt_def) = adt_def { + match adt_def.adt_kind() { + AdtKind::Enum => { + err.help("did you mean to use one of the enum's variants?"); + }, + AdtKind::Struct | + AdtKind::Union => { + err.span_suggestion( + span, + "use curly brackets", + String::from("Self { /* fields */ }"), + Applicability::HasPlaceholders, + ); + } + } + } + err.emit(); + + return (tcx.types.err, res) + } + } + } else { + (res, None) + }; let def_id = res.def_id(); // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. let ty = tcx.type_of(def_id); - let substs = AstConv::create_substs_for_generic_args( + let substs = self_ctor_substs.unwrap_or_else(|| AstConv::create_substs_for_generic_args( tcx, def_id, &[][..], @@ -5551,7 +5541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } }, - ); + )); assert!(!substs.has_escaping_bound_vars()); assert!(!ty.has_escaping_bound_vars()); diff --git a/src/test/run-pass/issues/issue-57924.rs b/src/test/ui/issues/issue-57924.rs similarity index 64% rename from src/test/run-pass/issues/issue-57924.rs rename to src/test/ui/issues/issue-57924.rs index 232596334b0..dc2942225e3 100644 --- a/src/test/run-pass/issues/issue-57924.rs +++ b/src/test/ui/issues/issue-57924.rs @@ -3,6 +3,7 @@ pub struct Gcm(E); impl Gcm { pub fn crash(e: E) -> Self { Self::(e) + //~^ ERROR type arguments are not allowed for this type } } diff --git a/src/test/ui/issues/issue-57924.stderr b/src/test/ui/issues/issue-57924.stderr new file mode 100644 index 00000000000..2f184b1aae1 --- /dev/null +++ b/src/test/ui/issues/issue-57924.stderr @@ -0,0 +1,9 @@ +error[E0109]: type arguments are not allowed for this type + --> $DIR/issue-57924.rs:5:16 + | +LL | Self::(e) + | ^ type argument not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/src/test/ui/issues/issue-61882-2.rs b/src/test/ui/issues/issue-61882-2.rs new file mode 100644 index 00000000000..1209b54bc41 --- /dev/null +++ b/src/test/ui/issues/issue-61882-2.rs @@ -0,0 +1,11 @@ +struct A(T); + +impl A<&'static u8> { + fn f() { + let x = 0; + Self(&x); + //~^ ERROR `x` does not live long enough + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-61882-2.stderr b/src/test/ui/issues/issue-61882-2.stderr new file mode 100644 index 00000000000..03a65540ced --- /dev/null +++ b/src/test/ui/issues/issue-61882-2.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-61882-2.rs:6:14 + | +LL | Self(&x); + | ^^ + | | + | borrowed value does not live long enough + | requires that `x` is borrowed for `'static` +LL | +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issues/issue-61882.rs b/src/test/ui/issues/issue-61882.rs new file mode 100644 index 00000000000..013398b4598 --- /dev/null +++ b/src/test/ui/issues/issue-61882.rs @@ -0,0 +1,9 @@ +struct A(T); + +impl A { + const B: A = Self(0); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/issues/issue-61882.stderr b/src/test/ui/issues/issue-61882.stderr new file mode 100644 index 00000000000..a14e1a4dd4d --- /dev/null +++ b/src/test/ui/issues/issue-61882.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-61882.rs:4:27 + | +LL | const B: A = Self(0); + | ^ expected bool, found integer + | + = note: expected type `bool` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/issue-61882.rs:4:22 + | +LL | const B: A = Self(0); + | ^^^^^^^ expected u8, found bool + | + = note: expected type `A` + found type `A` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`.