From a9f91b1b0e1b74d33d5b27b1811f7aa395314543 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 15 Sep 2016 00:51:46 +0300 Subject: [PATCH 1/3] Preparations and cleanup Diagnostics for struct path resolution errors in resolve and typeck are unified. Self type is treated as a type alias in few places (not reachable yet). Unsafe cell is seen in constants even through type aliases. All checks for struct paths in typeck work on type level. --- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc/util/ppaux.rs | 34 ++++- src/librustc_passes/consts.rs | 8 +- src/librustc_resolve/diagnostics.rs | 26 +--- src/librustc_resolve/lib.rs | 49 ++----- src/librustc_save_analysis/dump_visitor.rs | 3 +- src/librustc_typeck/astconv.rs | 28 +++- src/librustc_typeck/check/_match.rs | 3 +- src/librustc_typeck/check/mod.rs | 137 +++++++----------- src/librustc_typeck/diagnostics.rs | 11 +- src/test/compile-fail-fulldeps/issue-18986.rs | 2 +- src/test/compile-fail/E0071.rs | 9 +- .../compile-fail/enums-are-namespaced-xc.rs | 3 +- src/test/compile-fail/issue-16058.rs | 2 +- src/test/compile-fail/issue-17001.rs | 2 +- src/test/compile-fail/issue-17405.rs | 2 +- src/test/compile-fail/issue-17518.rs | 2 +- src/test/compile-fail/issue-21449.rs | 3 +- src/test/compile-fail/issue-26459.rs | 2 +- src/test/compile-fail/issue-27815.rs | 8 +- src/test/compile-fail/lexical-scopes.rs | 2 +- .../{E0422.rs => struct-path-alias-bounds.rs} | 14 +- .../struct-path-associated-type.rs | 48 ++++++ .../trait-as-struct-constructor.rs | 3 +- src/test/run-pass/issue-22546.rs | 3 + .../struct-path-associated-type.rs} | 30 ++-- 27 files changed, 232 insertions(+), 206 deletions(-) rename src/test/compile-fail/{E0422.rs => struct-path-alias-bounds.rs} (69%) create mode 100644 src/test/compile-fail/struct-path-associated-type.rs rename src/test/{compile-fail/struct-pat-associated-path.rs => run-pass/struct-path-associated-type.rs} (59%) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 799c02b740310..c37b6df369dfc 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1017,7 +1017,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { delegate.matched_pat(pat, downcast_cmt, match_mode); } Some(Def::Struct(..)) | Some(Def::StructCtor(..)) | Some(Def::Union(..)) | - Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => { + Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) | Some(Def::SelfTy(..)) => { debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat); delegate.matched_pat(pat, cmt_pat, match_mode); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f65976a8c110b..96700a8da86a3 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1698,7 +1698,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> { match def { Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid), Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) => self.struct_variant(), + Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.struct_variant(), _ => bug!("unexpected def {:?} in variant_of_def", def) } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index af92569cc350c..c0b5969fa9598 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -14,7 +14,7 @@ use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{TyBool, TyChar, TyAdt}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; -use ty::TyClosure; +use ty::{TyClosure, TyProjection, TyAnon}; use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer}; use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::fold::{TypeFolder, TypeVisitor}; @@ -802,6 +802,34 @@ impl<'tcx> fmt::Display for ty::TraitRef<'tcx> { } } +impl<'tcx> ty::TypeVariants<'tcx> { + pub fn descr(&self) -> &'static str { + match *self { + TyInt(..) | TyUint(..) | TyFloat(..) | + TyBool | TyChar | TyStr => "builtin type", + TyRawPtr(..) => "pointer", + TyRef(..) => "reference", + TyTuple(..) => "tuple", + TyFnDef(..) => "function type", + TyFnPtr(..) => "function pointer", + TyArray(..) => "array", + TySlice(..) => "slice", + TyParam(..) => "type parameter", + TyProjection(..) => "associated type", + TyTrait(..) => "trait type", + TyClosure(..) => "closure type", + TyBox(..) => "struct", + TyAdt(def, ..) => match def.adt_kind() { + ty::AdtKind::Struct => "struct", + ty::AdtKind::Union => "union", + ty::AdtKind::Enum => "enum", + }, + TyInfer(..) | TyAnon(..) | + TyNever | TyError => "type", + } + } +} + impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -879,8 +907,8 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { }) } TyTrait(ref data) => write!(f, "{}", data), - ty::TyProjection(ref data) => write!(f, "{}", data), - ty::TyAnon(def_id, substs) => { + TyProjection(ref data) => write!(f, "{}", data), + TyAnon(def_id, substs) => { ty::tls::with(|tcx| { // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index ee731dd042e4f..8ad4d7f57a6f0 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -565,9 +565,11 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprStruct(..) => { - // unsafe_cell_type doesn't necessarily exist with no_core - if Some(v.tcx.expect_def(e.id).def_id()) == v.tcx.lang_items.unsafe_cell_type() { - v.add_qualif(ConstQualif::MUTABLE_MEM); + if let ty::TyAdt(adt, ..) = v.tcx.expr_ty(e).sty { + // unsafe_cell_type doesn't necessarily exist with no_core + if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() { + v.add_qualif(ConstQualif::MUTABLE_MEM); + } } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index f2a5aedbb3ab4..1fb5db05dd508 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -860,31 +860,6 @@ match (A, B, C) { ``` "##, -E0422: r##" -You are trying to use an identifier that is either undefined or not a struct. - -Erroneous code example: - -``` compile_fail,E0422 -fn main () { - let x = Foo { x: 1, y: 2 }; -} -``` - -In this case, `Foo` is undefined, so it inherently isn't anything, and -definitely not a struct. - -```compile_fail,E0422 -fn main () { - let foo = 1; - let x = foo { x: 1, y: 2 }; -} -``` - -In this case, `foo` is defined, but is not a struct, so Rust can't use it as -one. -"##, - E0423: r##" A `struct` variant name was used like a function name. @@ -1503,6 +1478,7 @@ register_diagnostics! { // E0419, merged into 531 // E0420, merged into 532 // E0421, merged into 531 +// E0422, merged into 531/532 E0531, // unresolved pattern path kind `name` E0532, // expected pattern path kind, found another pattern path kind // E0427, merged into 530 diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 856eb348eaeec..d4900be575873 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -129,8 +129,6 @@ enum ResolutionError<'a> { IdentifierBoundMoreThanOnceInParameterList(&'a str), /// error E0416: identifier is bound more than once in the same pattern IdentifierBoundMoreThanOnceInSamePattern(&'a str), - /// error E0422: does not name a struct - DoesNotNameAStruct(&'a str), /// error E0423: is a struct variant name, but this expression uses it like a function name StructVariantUsedAsFunction(&'a str), /// error E0424: `self` is not available in a static method @@ -336,15 +334,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, err.span_label(span, &format!("used in a pattern more than once")); err } - ResolutionError::DoesNotNameAStruct(name) => { - let mut err = struct_span_err!(resolver.session, - span, - E0422, - "`{}` does not name a structure", - name); - err.span_label(span, &format!("not a structure")); - err - } ResolutionError::StructVariantUsedAsFunction(path_name) => { let mut err = struct_span_err!(resolver.session, span, @@ -2383,6 +2372,18 @@ impl<'a> Resolver<'a> { self.record_def(pat_id, resolution); } + fn resolve_struct_path(&mut self, node_id: NodeId, path: &Path) { + // Resolution logic is equivalent for expressions and patterns, + // reuse `resolve_pattern_path` for both. + self.resolve_pattern_path(node_id, None, path, TypeNS, |def| { + match def { + Def::Struct(..) | Def::Union(..) | Def::Variant(..) | + Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true, + _ => false, + } + }, "struct, variant or union type"); + } + fn resolve_pattern(&mut self, pat: &Pat, pat_src: PatternSource, @@ -2460,13 +2461,7 @@ impl<'a> Resolver<'a> { } PatKind::Struct(ref path, ..) => { - self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| { - match def { - Def::Struct(..) | Def::Union(..) | Def::Variant(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) => true, - _ => false, - } - }, "variant, struct or type alias"); + self.resolve_struct_path(pat.id, path); } _ => {} @@ -3024,23 +3019,7 @@ impl<'a> Resolver<'a> { } ExprKind::Struct(ref path, ..) => { - // Resolve the path to the structure it goes to. We don't - // check to ensure that the path is actually a structure; that - // is checked later during typeck. - match self.resolve_path(expr.id, path, 0, TypeNS) { - Ok(definition) => self.record_def(expr.id, definition), - Err(true) => self.record_def(expr.id, err_path_resolution()), - Err(false) => { - debug!("(resolving expression) didn't find struct def",); - - resolve_error(self, - path.span, - ResolutionError::DoesNotNameAStruct( - &path_names_to_string(path, 0)) - ); - self.record_def(expr.id, err_path_resolution()); - } - } + self.resolve_struct_path(expr.id, path); visit::walk_expr(self, expr); } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 1c60ccb976588..53a5f3193231d 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1493,7 +1493,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | Def::AssociatedConst(..) | Def::Struct(..) | Def::Variant(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) => { + Def::TyAlias(..) | Def::AssociatedTy(..) | + Def::SelfTy(..) => { paths_to_process.push((id, p.clone(), Some(ref_kind))) } def => error!("unexpected definition kind when processing collected paths: {:?}", diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c137fca58afb9..0c71b0424ae6d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1484,7 +1484,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { def: Def, opt_self_ty: Option>, base_path_ref_id: ast::NodeId, - base_segments: &[hir::PathSegment]) + base_segments: &[hir::PathSegment], + permit_variants: bool) -> Ty<'tcx> { let tcx = self.tcx(); @@ -1515,6 +1516,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { did, base_segments.last().unwrap()) } + Def::Variant(did) if permit_variants => { + // Convert "variant type" as if it were a real type. + // The resulting `Ty` is type of the variant's enum for now. + tcx.prohibit_type_params(base_segments.split_last().unwrap().1); + let mut ty = self.ast_path_to_ty(rscope, + span, + param_mode, + tcx.parent_def_id(did).unwrap(), + base_segments.last().unwrap()); + if ty.is_fn() { + // Tuple variants have fn type even in type namespace, + // extract true variant type from it. + ty = tcx.no_late_bound_regions(&ty.fn_ret()).unwrap(); + } + ty + } Def::TyParam(did) => { tcx.prohibit_type_params(base_segments); @@ -1604,7 +1621,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { opt_self_ty: Option>, base_path_ref_id: ast::NodeId, base_segments: &[hir::PathSegment], - assoc_segments: &[hir::PathSegment]) + assoc_segments: &[hir::PathSegment], + permit_variants: bool) -> (Ty<'tcx>, Def) { // Convert the base type. debug!("finish_resolving_def_to_ty(base_def={:?}, \ @@ -1619,7 +1637,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { base_def, opt_self_ty, base_path_ref_id, - base_segments); + base_segments, + permit_variants); debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty); // If any associated type segments remain, attempt to resolve them. @@ -1775,7 +1794,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { opt_self_ty, ast_ty.id, &path.segments[..base_ty_end], - &path.segments[base_ty_end..]); + &path.segments[base_ty_end..], + false); // Write back the new resolution. if path_res.depth != 0 { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index d3fef0711b246..c842514227ca0 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -489,8 +489,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected: Ty<'tcx>) -> Ty<'tcx> { // Resolve the path and check the definition for errors. - let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id, - pat.span) { + let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id) { variant_ty } else { for field in fields { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 21da8cd388cd9..1c29867bfb8fa 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1686,41 +1686,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { cause) } - /// Instantiates the type in `did` with the generics in `path` and returns - /// it (registering the necessary trait obligations along the way). - /// - /// Note that this function is only intended to be used with type-paths, - /// not with value-paths. - pub fn instantiate_type_path(&self, - did: DefId, - path: &hir::Path, - node_id: ast::NodeId) - -> Ty<'tcx> { - debug!("instantiate_type_path(did={:?}, path={:?})", did, path); - let mut ty = self.tcx.lookup_item_type(did).ty; - if ty.is_fn() { - // Tuple variants have fn type even in type namespace, extract true variant type from it - ty = self.tcx.no_late_bound_regions(&ty.fn_ret()).unwrap(); - } - let type_predicates = self.tcx.lookup_predicates(did); - let substs = AstConv::ast_path_substs_for_ty(self, self, - path.span, - PathParamMode::Optional, - did, - path.segments.last().unwrap()); - debug!("instantiate_type_path: ty={:?} substs={:?}", ty, substs); - let bounds = self.instantiate_bounds(path.span, substs, &type_predicates); - let cause = traits::ObligationCause::new(path.span, self.body_id, - traits::ItemObligation(did)); - self.add_obligations_for_parameters(cause, &bounds); - - let ty_substituted = self.instantiate_type_scheme(path.span, substs, &ty); - self.write_substs(node_id, ty::ItemSubsts { - substs: substs - }); - ty_substituted - } - pub fn write_nil(&self, node_id: ast::NodeId) { self.write_ty(node_id, self.tcx.mk_nil()); } @@ -3252,46 +3217,56 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_struct_path(&self, path: &hir::Path, - node_id: ast::NodeId, - span: Span) + node_id: ast::NodeId) -> Option<(ty::VariantDef<'tcx>, Ty<'tcx>)> { - let def = self.finish_resolving_struct_path(path, node_id, span); + let (def, ty) = self.finish_resolving_struct_path(path, node_id); let variant = match def { Def::Err => { self.set_tainted_by_errors(); return None; } - Def::Variant(did) => { - let type_did = self.tcx.parent_def_id(did).unwrap(); - Some((type_did, self.tcx.expect_variant_def(def))) - } - Def::Struct(type_did) | Def::Union(type_did) => { - Some((type_did, self.tcx.expect_variant_def(def))) + Def::Variant(..) => { + match ty.sty { + ty::TyAdt(adt, substs) => { + Some((adt.variant_of_def(def), adt.did, substs)) + } + _ => bug!("unexpected type: {:?}", ty.sty) + } } - Def::TyAlias(did) | Def::AssociatedTy(did) => { - match self.tcx.opt_lookup_item_type(did).map(|scheme| &scheme.ty.sty) { - Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => { - Some((did, adt.struct_variant())) + Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | + Def::AssociatedTy(..) => { + match ty.sty { + ty::TyAdt(adt, substs) if !adt.is_enum() => { + Some((adt.struct_variant(), adt.did, substs)) } _ => None, } } - _ => None + // Self is not supported yet. + Def::SelfTy(..) => None, + _ => bug!("unexpected definition: {:?}", def) }; - if let Some((def_id, variant)) = variant { + if let Some((variant, did, substs)) = variant { if variant.ctor_kind == CtorKind::Fn && !self.tcx.sess.features.borrow().relaxed_adts { emit_feature_err(&self.tcx.sess.parse_sess, - "relaxed_adts", span, GateIssue::Language, + "relaxed_adts", path.span, GateIssue::Language, "tuple structs and variants in struct patterns are unstable"); } - let ty = self.instantiate_type_path(def_id, path, node_id); + + // Check bounds on type arguments used in the path. + let type_predicates = self.tcx.lookup_predicates(did); + let bounds = self.instantiate_bounds(path.span, substs, &type_predicates); + let cause = traits::ObligationCause::new(path.span, self.body_id, + traits::ItemObligation(did)); + self.add_obligations_for_parameters(cause, &bounds); + Some((variant, ty)) } else { struct_span_err!(self.tcx.sess, path.span, E0071, - "`{}` does not name a struct or a struct variant", - pprust::path_to_string(path)) + "expected struct, variant or union type, found {} `{}`", + ty.sty.descr(), ty) .span_label(path.span, &format!("not a struct")) .emit(); None @@ -3305,12 +3280,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { base_expr: &'gcx Option>) -> Ty<'tcx> { // Find the relevant variant - let (variant, struct_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id, - expr.span) { + let (variant, struct_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id) { variant_ty } else { self.check_struct_fields_on_error(fields, base_expr); - return self.tcx().types.err; + return self.tcx.types.err; }; self.check_expr_struct_fields(struct_ty, path.span, variant, fields, @@ -3805,7 +3779,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } err.emit(); - self.tcx().types.err + self.tcx.types.err } } } @@ -3815,29 +3789,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. // The newly resolved definition is written into `def_map`. - pub fn finish_resolving_struct_path(&self, - path: &hir::Path, - node_id: ast::NodeId, - span: Span) - -> Def + fn finish_resolving_struct_path(&self, + path: &hir::Path, + node_id: ast::NodeId) + -> (Def, Ty<'tcx>) { - let path_res = self.tcx().expect_resolution(node_id); - if path_res.depth == 0 { - // If fully resolved already, we don't have to do anything. - path_res.base_def - } else { - let base_ty_end = path.segments.len() - path_res.depth; - let (_ty, def) = AstConv::finish_resolving_def_to_ty(self, self, span, - PathParamMode::Optional, - path_res.base_def, - None, - node_id, - &path.segments[..base_ty_end], - &path.segments[base_ty_end..]); - // Write back the new resolution. - self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def)); - def + let path_res = self.tcx.expect_resolution(node_id); + let base_ty_end = path.segments.len() - path_res.depth; + let (ty, def) = AstConv::finish_resolving_def_to_ty(self, self, path.span, + PathParamMode::Optional, + path_res.base_def, + None, + node_id, + &path.segments[..base_ty_end], + &path.segments[base_ty_end..], + true); + // Write back the new resolution. + if path_res.depth != 0 { + self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def)); } + (def, ty) } // Resolve associated value path into a base type and associated constant or method definition. @@ -3849,7 +3820,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span) -> (Def, Option>, &'b [hir::PathSegment]) { - let path_res = self.tcx().expect_resolution(node_id); + let path_res = self.tcx.expect_resolution(node_id); if path_res.depth == 0 { // If fully resolved already, we don't have to do anything. (path_res.base_def, opt_self_ty, &path.segments) @@ -3863,7 +3834,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { opt_self_ty, node_id, &ty_segments[..base_ty_end], - &ty_segments[base_ty_end..]); + &ty_segments[base_ty_end..], + false); // Resolve an associated constant or method on the previously resolved type. let item_segment = path.segments.last().unwrap(); @@ -3883,7 +3855,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Write back the new resolution. - self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def)); + self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def)); (def, Some(ty), slice::ref_slice(item_segment)) } } @@ -4308,7 +4280,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // the referenced item. let ty_substituted = self.instantiate_type_scheme(span, &substs, &scheme.ty); - if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated { // In the case of `Foo::method` and `>::method`, if `method` // is inherent, there is no `Self` parameter, instead, the impl needs diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 189f8490f6c1d..7dd850180d442 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -895,17 +895,14 @@ fn some_func(x: &mut i32) { E0071: r##" You tried to use structure-literal syntax to create an item that is -not a struct-style structure or enum variant. +not a structure or enum variant. Example of erroneous code: ```compile_fail,E0071 -enum Foo { FirstValue(i32) }; - -let u = Foo::FirstValue { value: 0 }; // error: Foo::FirstValue - // isn't a structure! -// or even simpler, if the name doesn't refer to a structure at all. -let t = u32 { value: 4 }; // error: `u32` does not name a structure. +type U32 = u32; +let t = U32 { value: 4 }; // error: expected struct, variant or union type, + // found builtin type `u32` ``` To fix this, ensure that the name was correctly spelled, and that diff --git a/src/test/compile-fail-fulldeps/issue-18986.rs b/src/test/compile-fail-fulldeps/issue-18986.rs index 3c32cb947b382..95af37605441d 100644 --- a/src/test/compile-fail-fulldeps/issue-18986.rs +++ b/src/test/compile-fail-fulldeps/issue-18986.rs @@ -15,6 +15,6 @@ pub use use_from_trait_xc::Trait; fn main() { match () { - Trait { x: 42 } => () //~ ERROR expected variant, struct or type alias, found trait `Trait` + Trait { x: 42 } => () //~ ERROR expected struct, variant or union type, found trait `Trait` } } diff --git a/src/test/compile-fail/E0071.rs b/src/test/compile-fail/E0071.rs index c13ba7bf13671..95653ae83e7cd 100644 --- a/src/test/compile-fail/E0071.rs +++ b/src/test/compile-fail/E0071.rs @@ -9,13 +9,10 @@ // except according to those terms. enum Foo {} +type FooAlias = Foo; fn main() { - let u = Foo { value: 0 }; - //~^ ERROR `Foo` does not name a struct or a struct variant [E0071] - //~| NOTE not a struct - - let t = u32 { value: 4 }; - //~^ ERROR `u32` does not name a struct or a struct variant [E0071] + let u = FooAlias { value: 0 }; + //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071] //~| NOTE not a struct } diff --git a/src/test/compile-fail/enums-are-namespaced-xc.rs b/src/test/compile-fail/enums-are-namespaced-xc.rs index 5315e6c834ab3..02939565f69cd 100644 --- a/src/test/compile-fail/enums-are-namespaced-xc.rs +++ b/src/test/compile-fail/enums-are-namespaced-xc.rs @@ -14,5 +14,6 @@ extern crate namespaced_enums; fn main() { let _ = namespaced_enums::A; //~ ERROR unresolved name let _ = namespaced_enums::B(10); //~ ERROR unresolved name - let _ = namespaced_enums::C { a: 10 }; //~ ERROR does not name a structure + let _ = namespaced_enums::C { a: 10 }; + //~^ ERROR unresolved struct, variant or union type `namespaced_enums::C` } diff --git a/src/test/compile-fail/issue-16058.rs b/src/test/compile-fail/issue-16058.rs index 671232e701f87..92c1e4b5f5060 100644 --- a/src/test/compile-fail/issue-16058.rs +++ b/src/test/compile-fail/issue-16058.rs @@ -16,7 +16,7 @@ pub struct GslResult { impl GslResult { pub fn new() -> GslResult { - Result { //~ ERROR: `Result` does not name a struct or a struct variant + Result { //~ ERROR: expected struct, variant or union type, found enum `Result` val: 0f64, err: 0f64 } diff --git a/src/test/compile-fail/issue-17001.rs b/src/test/compile-fail/issue-17001.rs index 218f68714ff92..413e8b464fff7 100644 --- a/src/test/compile-fail/issue-17001.rs +++ b/src/test/compile-fail/issue-17001.rs @@ -11,5 +11,5 @@ mod foo {} fn main() { - let p = foo { x: () }; //~ ERROR `foo` does not name a struct or a struct variant + let p = foo { x: () }; //~ ERROR expected struct, variant or union type, found module `foo` } diff --git a/src/test/compile-fail/issue-17405.rs b/src/test/compile-fail/issue-17405.rs index 2f2c252b947c9..5a6bd5ed588a6 100644 --- a/src/test/compile-fail/issue-17405.rs +++ b/src/test/compile-fail/issue-17405.rs @@ -14,6 +14,6 @@ enum Foo { fn main() { match Foo::Bar(1) { - Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo` + Foo { i } => () //~ ERROR expected struct, variant or union type, found enum `Foo` } } diff --git a/src/test/compile-fail/issue-17518.rs b/src/test/compile-fail/issue-17518.rs index 0410fadeb7892..2113e38c45cc3 100644 --- a/src/test/compile-fail/issue-17518.rs +++ b/src/test/compile-fail/issue-17518.rs @@ -13,5 +13,5 @@ enum SomeEnum { } fn main() { - E { name: "foobar" }; //~ ERROR `E` does not name a structure + E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E` } diff --git a/src/test/compile-fail/issue-21449.rs b/src/test/compile-fail/issue-21449.rs index 090b8a0d16e64..cc44cf88f09bd 100644 --- a/src/test/compile-fail/issue-21449.rs +++ b/src/test/compile-fail/issue-21449.rs @@ -11,5 +11,6 @@ mod MyMod {} fn main() { - let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a struct or a struct variant + let myVar = MyMod { T: 0 }; + //~^ ERROR expected struct, variant or union type, found module `MyMod` } diff --git a/src/test/compile-fail/issue-26459.rs b/src/test/compile-fail/issue-26459.rs index 24b39eeff0f79..8be3d88bd5c8f 100644 --- a/src/test/compile-fail/issue-26459.rs +++ b/src/test/compile-fail/issue-26459.rs @@ -11,6 +11,6 @@ fn main() { match 'a' { char{ch} => true - //~^ ERROR expected variant, struct or type alias, found builtin type `char` + //~^ ERROR expected struct, variant or union type, found builtin type `char` }; } diff --git a/src/test/compile-fail/issue-27815.rs b/src/test/compile-fail/issue-27815.rs index 33930d1db1476..d9840abf0ca77 100644 --- a/src/test/compile-fail/issue-27815.rs +++ b/src/test/compile-fail/issue-27815.rs @@ -11,12 +11,12 @@ mod A {} fn main() { - let u = A { x: 1 }; //~ ERROR `A` does not name a struct or a struct variant - let v = u32 { x: 1 }; //~ ERROR `u32` does not name a struct or a struct variant + let u = A { x: 1 }; //~ ERROR expected struct, variant or union type, found module `A` + let v = u32 { x: 1 }; //~ ERROR expected struct, variant or union type, found builtin type `u32` match () { A { x: 1 } => {} - //~^ ERROR expected variant, struct or type alias, found module `A` + //~^ ERROR expected struct, variant or union type, found module `A` u32 { x: 1 } => {} - //~^ ERROR expected variant, struct or type alias, found builtin type `u32` + //~^ ERROR expected struct, variant or union type, found builtin type `u32` } } diff --git a/src/test/compile-fail/lexical-scopes.rs b/src/test/compile-fail/lexical-scopes.rs index 505a91f223cc6..1ab59e790d7ee 100644 --- a/src/test/compile-fail/lexical-scopes.rs +++ b/src/test/compile-fail/lexical-scopes.rs @@ -10,7 +10,7 @@ struct T { i: i32 } fn f() { - let t = T { i: 0 }; //~ ERROR `T` does not name a struct or a struct variant + let t = T { i: 0 }; //~ ERROR expected struct, variant or union type, found type parameter `T` } mod Foo { diff --git a/src/test/compile-fail/E0422.rs b/src/test/compile-fail/struct-path-alias-bounds.rs similarity index 69% rename from src/test/compile-fail/E0422.rs rename to src/test/compile-fail/struct-path-alias-bounds.rs index 61e96b896a66a..1b6e51e37034e 100644 --- a/src/test/compile-fail/E0422.rs +++ b/src/test/compile-fail/struct-path-alias-bounds.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main () { - let x = Foo { x: 1, y: 2 }; - //~^ ERROR E0422 - //~| NOTE not a structure +// issue #36286 + +struct S { a: T } + +struct NoClone; +type A = S; + +fn main() { + let s = A { a: NoClone }; + //~^ ERROR the trait bound `NoClone: std::clone::Clone` is not satisfied } diff --git a/src/test/compile-fail/struct-path-associated-type.rs b/src/test/compile-fail/struct-path-associated-type.rs new file mode 100644 index 0000000000000..2f7330cb391b2 --- /dev/null +++ b/src/test/compile-fail/struct-path-associated-type.rs @@ -0,0 +1,48 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +trait Tr { + type A; +} + +impl Tr for S { + type A = S; +} + +fn f() { + let s = T::A {}; + //~^ ERROR expected struct, variant or union type, found associated type `::A` + let z = T::A:: {}; + //~^ ERROR expected struct, variant or union type, found associated type `::A` + //~| ERROR type parameters are not allowed on this type + match S { + T::A {} => {} + //~^ ERROR expected struct, variant or union type, found associated type `::A` + } +} + +fn g>() { + let s = T::A {}; // OK + let z = T::A:: {}; //~ ERROR type parameters are not allowed on this type + match S { + T::A {} => {} // OK + } +} + +fn main() { + let s = S::A {}; //~ ERROR ambiguous associated type + let z = S::A:: {}; //~ ERROR ambiguous associated type + //~^ ERROR type parameters are not allowed on this type + match S { + S::A {} => {} //~ ERROR ambiguous associated type + } +} diff --git a/src/test/compile-fail/trait-as-struct-constructor.rs b/src/test/compile-fail/trait-as-struct-constructor.rs index c78eebddbfdb8..49d58580da52d 100644 --- a/src/test/compile-fail/trait-as-struct-constructor.rs +++ b/src/test/compile-fail/trait-as-struct-constructor.rs @@ -12,6 +12,5 @@ trait TraitNotAStruct {} fn main() { TraitNotAStruct{ value: 0 }; - //~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071] - //~| NOTE not a struct + //~^ ERROR expected struct, variant or union type, found trait `TraitNotAStruct` } diff --git a/src/test/run-pass/issue-22546.rs b/src/test/run-pass/issue-22546.rs index b3cb8a78213b8..fd9eb1f87c743 100644 --- a/src/test/run-pass/issue-22546.rs +++ b/src/test/run-pass/issue-22546.rs @@ -51,4 +51,7 @@ fn main() { if let None:: = Some(8) { panic!(); } + if let None:: { .. } = Some(8) { + panic!(); + } } diff --git a/src/test/compile-fail/struct-pat-associated-path.rs b/src/test/run-pass/struct-path-associated-type.rs similarity index 59% rename from src/test/compile-fail/struct-pat-associated-path.rs rename to src/test/run-pass/struct-path-associated-type.rs index d3f840f4fe976..b033ed5c80210 100644 --- a/src/test/compile-fail/struct-pat-associated-path.rs +++ b/src/test/run-pass/struct-path-associated-type.rs @@ -8,30 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct S; +struct S { + a: T, + b: U, +} trait Tr { type A; } - -impl Tr for S { - type A = S; -} - -fn f() { - match S { - T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant - } +impl Tr for u8 { + type A = S; } -fn g>() { - match S { - T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant +fn f>>() { + let s = T::A { a: 0, b: 1 }; + match s { + T::A { a, b } => { + assert_eq!(a, 0); + assert_eq!(b, 1); + } } } fn main() { - match S { - S::A {} => {} //~ ERROR ambiguous associated type - } + f::(); } From eada951f9c302d531d6b9ad474e87faafea9a5d5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 15 Sep 2016 00:51:46 +0300 Subject: [PATCH 2/3] Support `Self` in struct expressions and patterns --- src/librustc_typeck/check/mod.rs | 4 +- src/test/compile-fail/struct-path-self.rs | 47 ++++++++++++++++++++ src/test/run-pass/struct-path-self.rs | 54 +++++++++++++++++++++++ 3 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/struct-path-self.rs create mode 100644 src/test/run-pass/struct-path-self.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1c29867bfb8fa..7f6c98efa4d47 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3234,7 +3234,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | - Def::AssociatedTy(..) => { + Def::AssociatedTy(..) | Def::SelfTy(..) => { match ty.sty { ty::TyAdt(adt, substs) if !adt.is_enum() => { Some((adt.struct_variant(), adt.did, substs)) @@ -3242,8 +3242,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => None, } } - // Self is not supported yet. - Def::SelfTy(..) => None, _ => bug!("unexpected definition: {:?}", def) }; diff --git a/src/test/compile-fail/struct-path-self.rs b/src/test/compile-fail/struct-path-self.rs new file mode 100644 index 0000000000000..d76b9fda8bf82 --- /dev/null +++ b/src/test/compile-fail/struct-path-self.rs @@ -0,0 +1,47 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +trait Tr { + fn f() { + let s = Self {}; + //~^ ERROR expected struct, variant or union type, found type parameter `Self` + let z = Self:: {}; + //~^ ERROR expected struct, variant or union type, found type parameter `Self` + //~| ERROR type parameters are not allowed on this type + match s { + Self { .. } => {} + //~^ ERROR expected struct, variant or union type, found type parameter `Self` + } + } +} + +impl Tr for S { + fn f() { + let s = Self {}; // OK + let z = Self:: {}; //~ ERROR type parameters are not allowed on this type + match s { + Self { .. } => {} // OK + } + } +} + +impl S { + fn g() { + let s = Self {}; // OK + let z = Self:: {}; //~ ERROR type parameters are not allowed on this type + match s { + Self { .. } => {} // OK + } + } +} + +fn main() {} diff --git a/src/test/run-pass/struct-path-self.rs b/src/test/run-pass/struct-path-self.rs new file mode 100644 index 0000000000000..c7a282c2a2fa0 --- /dev/null +++ b/src/test/run-pass/struct-path-self.rs @@ -0,0 +1,54 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Add; + +struct S { + a: T, + b: U, +} + +trait Tr { + fn f(&self) -> Self; +} + +impl, U: Default> Tr for S { + fn f(&self) -> Self { + let s = Self { a: Default::default(), b: Default::default() }; + match s { + Self { a, b } => Self { a: a + 1, b: b } + } + } +} + +impl> S { + fn g(&self) -> Self { + let s = Self { a: Default::default(), b: Default::default() }; + match s { + Self { a, b } => Self { a: a, b: b + 1 } + } + } +} + +impl S { + fn new() -> Self { + Self { a: 0, b: 1 } + } +} + +fn main() { + let s0 = S::new(); + let s1 = s0.f(); + assert_eq!(s1.a, 1); + assert_eq!(s1.b, 0); + let s2 = s0.g(); + assert_eq!(s2.a, 0); + assert_eq!(s2.b, 1); +} From 8a38928b44e26d4d7b9bdacb207a85878058cac8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 15 Sep 2016 00:51:46 +0300 Subject: [PATCH 3/3] Address comments + Fix rebase --- src/librustc/util/ppaux.rs | 28 -------------- src/librustc_const_eval/pattern.rs | 2 +- src/librustc_typeck/astconv.rs | 16 +++----- src/librustc_typeck/check/mod.rs | 10 ++--- .../struct-path-associated-type.rs | 6 +-- .../struct-path-self-type-mismatch.rs | 38 +++++++++++++++++++ src/test/compile-fail/struct-path-self.rs | 6 +-- src/test/run-pass/issue-22546.rs | 3 ++ 8 files changed, 58 insertions(+), 51 deletions(-) create mode 100644 src/test/compile-fail/struct-path-self-type-mismatch.rs diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index c0b5969fa9598..13202a454fe55 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -802,34 +802,6 @@ impl<'tcx> fmt::Display for ty::TraitRef<'tcx> { } } -impl<'tcx> ty::TypeVariants<'tcx> { - pub fn descr(&self) -> &'static str { - match *self { - TyInt(..) | TyUint(..) | TyFloat(..) | - TyBool | TyChar | TyStr => "builtin type", - TyRawPtr(..) => "pointer", - TyRef(..) => "reference", - TyTuple(..) => "tuple", - TyFnDef(..) => "function type", - TyFnPtr(..) => "function pointer", - TyArray(..) => "array", - TySlice(..) => "slice", - TyParam(..) => "type parameter", - TyProjection(..) => "associated type", - TyTrait(..) => "trait type", - TyClosure(..) => "closure type", - TyBox(..) => "struct", - TyAdt(def, ..) => match def.adt_kind() { - ty::AdtKind::Struct => "struct", - ty::AdtKind::Union => "union", - ty::AdtKind::Enum => "enum", - }, - TyInfer(..) | TyAnon(..) | - TyNever | TyError => "type", - } - } -} - impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index a6c886533c86c..f4dedc184d96a 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -436,7 +436,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) => { + Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { PatternKind::Leaf { subpatterns: subpatterns } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0c71b0424ae6d..8799050b1b999 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1520,17 +1520,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Convert "variant type" as if it were a real type. // The resulting `Ty` is type of the variant's enum for now. tcx.prohibit_type_params(base_segments.split_last().unwrap().1); - let mut ty = self.ast_path_to_ty(rscope, - span, - param_mode, - tcx.parent_def_id(did).unwrap(), - base_segments.last().unwrap()); - if ty.is_fn() { - // Tuple variants have fn type even in type namespace, - // extract true variant type from it. - ty = tcx.no_late_bound_regions(&ty.fn_ret()).unwrap(); - } - ty + self.ast_path_to_ty(rscope, + span, + param_mode, + tcx.parent_def_id(did).unwrap(), + base_segments.last().unwrap()) } Def::TyParam(did) => { tcx.prohibit_type_params(base_segments); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7f6c98efa4d47..75a14bb3db922 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3216,9 +3216,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_struct_path(&self, - path: &hir::Path, - node_id: ast::NodeId) - -> Option<(ty::VariantDef<'tcx>, Ty<'tcx>)> { + path: &hir::Path, + node_id: ast::NodeId) + -> Option<(ty::VariantDef<'tcx>, Ty<'tcx>)> { let (def, ty) = self.finish_resolving_struct_path(path, node_id); let variant = match def { Def::Err => { @@ -3263,8 +3263,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some((variant, ty)) } else { struct_span_err!(self.tcx.sess, path.span, E0071, - "expected struct, variant or union type, found {} `{}`", - ty.sty.descr(), ty) + "expected struct, variant or union type, found {}", + ty.sort_string(self.tcx)) .span_label(path.span, &format!("not a struct")) .emit(); None diff --git a/src/test/compile-fail/struct-path-associated-type.rs b/src/test/compile-fail/struct-path-associated-type.rs index 2f7330cb391b2..660ac44ce0b53 100644 --- a/src/test/compile-fail/struct-path-associated-type.rs +++ b/src/test/compile-fail/struct-path-associated-type.rs @@ -20,13 +20,13 @@ impl Tr for S { fn f() { let s = T::A {}; - //~^ ERROR expected struct, variant or union type, found associated type `::A` + //~^ ERROR expected struct, variant or union type, found associated type let z = T::A:: {}; - //~^ ERROR expected struct, variant or union type, found associated type `::A` + //~^ ERROR expected struct, variant or union type, found associated type //~| ERROR type parameters are not allowed on this type match S { T::A {} => {} - //~^ ERROR expected struct, variant or union type, found associated type `::A` + //~^ ERROR expected struct, variant or union type, found associated type } } diff --git a/src/test/compile-fail/struct-path-self-type-mismatch.rs b/src/test/compile-fail/struct-path-self-type-mismatch.rs new file mode 100644 index 0000000000000..f694e7d277c7f --- /dev/null +++ b/src/test/compile-fail/struct-path-self-type-mismatch.rs @@ -0,0 +1,38 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { inner: A } + +trait Bar { fn bar(); } + +impl Bar for Foo { + fn bar() { + Self { inner: 1.5f32 }; //~ ERROR mismatched types + //~^ NOTE expected i32, found f32 + } +} + +impl Foo { + fn new(u: U) -> Foo { + Self { + //~^ ERROR mismatched types + //~| expected type parameter, found a different type parameter + //~| expected type `Foo` + //~| found type `Foo` + inner: u + //~^ ERROR mismatched types + //~| expected type parameter, found a different type parameter + //~| expected type `T` + //~| found type `U` + } + } +} + +fn main() {} diff --git a/src/test/compile-fail/struct-path-self.rs b/src/test/compile-fail/struct-path-self.rs index d76b9fda8bf82..067d6ac22dc6f 100644 --- a/src/test/compile-fail/struct-path-self.rs +++ b/src/test/compile-fail/struct-path-self.rs @@ -13,13 +13,13 @@ struct S; trait Tr { fn f() { let s = Self {}; - //~^ ERROR expected struct, variant or union type, found type parameter `Self` + //~^ ERROR expected struct, variant or union type, found Self let z = Self:: {}; - //~^ ERROR expected struct, variant or union type, found type parameter `Self` + //~^ ERROR expected struct, variant or union type, found Self //~| ERROR type parameters are not allowed on this type match s { Self { .. } => {} - //~^ ERROR expected struct, variant or union type, found type parameter `Self` + //~^ ERROR expected struct, variant or union type, found Self } } } diff --git a/src/test/run-pass/issue-22546.rs b/src/test/run-pass/issue-22546.rs index fd9eb1f87c743..8516d344e1cdc 100644 --- a/src/test/run-pass/issue-22546.rs +++ b/src/test/run-pass/issue-22546.rs @@ -54,4 +54,7 @@ fn main() { if let None:: { .. } = Some(8) { panic!(); } + if let Option::None:: { .. } = Some(8) { + panic!(); + } }