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.
This commit is contained in:
Vadim Petrochenkov 2016-09-15 00:51:46 +03:00
parent 07436946b6
commit a9f91b1b0e
27 changed files with 232 additions and 206 deletions

View File

@ -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);
}

View File

@ -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)
}
}

View File

@ -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.

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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: {:?}",

View File

@ -1484,7 +1484,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
def: Def,
opt_self_ty: Option<Ty<'tcx>>,
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<Ty<'tcx>>,
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 {

View File

@ -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 {

View File

@ -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::Variant(..) => {
match ty.sty {
ty::TyAdt(adt, substs) => {
Some((adt.variant_of_def(def), adt.did, substs))
}
_ => bug!("unexpected type: {:?}", ty.sty)
}
}
Def::Struct(type_did) | Def::Union(type_did) => {
Some((type_did, self.tcx.expect_variant_def(def)))
}
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<P<hir::Expr>>) -> 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<Ty<'tcx>>, &'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<T>::method` and `<Foo<T>>::method`, if `method`
// is inherent, there is no `Self` parameter, instead, the impl needs

View File

@ -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

View File

@ -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`
}
}

View File

@ -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
}

View File

@ -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`
}

View File

@ -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
}

View File

@ -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`
}

View File

@ -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`
}
}

View File

@ -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`
}

View File

@ -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`
}

View File

@ -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`
};
}

View File

@ -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`
}
}

View File

@ -10,7 +10,7 @@
struct T { i: i32 }
fn f<T>() {
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 {

View File

@ -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<T: Clone> { a: T }
struct NoClone;
type A = S<NoClone>;
fn main() {
let s = A { a: NoClone };
//~^ ERROR the trait bound `NoClone: std::clone::Clone` is not satisfied
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Tr>() {
let s = T::A {};
//~^ ERROR expected struct, variant or union type, found associated type `<T as Tr>::A`
let z = T::A::<u8> {};
//~^ ERROR expected struct, variant or union type, found associated type `<T as Tr>::A`
//~| ERROR type parameters are not allowed on this type
match S {
T::A {} => {}
//~^ ERROR expected struct, variant or union type, found associated type `<T as Tr>::A`
}
}
fn g<T: Tr<A = S>>() {
let s = T::A {}; // OK
let z = T::A::<u8> {}; //~ 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::<u8> {}; //~ ERROR ambiguous associated type
//~^ ERROR type parameters are not allowed on this type
match S {
S::A {} => {} //~ ERROR ambiguous associated type
}
}

View File

@ -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`
}

View File

@ -51,4 +51,7 @@ fn main() {
if let None::<u8> = Some(8) {
panic!();
}
if let None::<u8> { .. } = Some(8) {
panic!();
}
}

View File

@ -8,30 +8,28 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct S;
struct S<T, U = u16> {
a: T,
b: U,
}
trait Tr {
type A;
}
impl Tr for S {
type A = S;
impl Tr for u8 {
type A = S<u8, u16>;
}
fn f<T: Tr>() {
match S {
T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant
}
}
fn g<T: Tr<A = S>>() {
match S {
T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant
fn f<T: Tr<A = S<u8>>>() {
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::<u8>();
}