提交 a9f91b1b 编写于 作者: V Vadim Petrochenkov

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.
上级 07436946
......@@ -1017,7 +1017,7 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
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);
}
......
......@@ -1698,7 +1698,7 @@ pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'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)
}
}
......
......@@ -14,7 +14,7 @@
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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
})
}
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.
......
......@@ -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);
}
}
}
......
......@@ -860,31 +860,6 @@ fn foo(f: i32, g: i32) {} // ok!
```
"##,
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 @@ fn main() {
// 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
......
......@@ -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 @@ fn resolve_pattern_path<ExpectedFn>(&mut self,
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 @@ fn resolve_pattern(&mut self,
}
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 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
}
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);
}
......
......@@ -1493,7 +1493,8 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
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: {:?}",
......
......@@ -1484,7 +1484,8 @@ fn base_def_to_ty(&self,
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 @@ fn base_def_to_ty(&self,
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 @@ pub fn finish_resolving_def_to_ty(&self,
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 @@ pub fn finish_resolving_def_to_ty(&self,
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 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
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 {
......
......@@ -489,8 +489,7 @@ fn check_pat_struct(&self,
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 {
......
......@@ -1686,41 +1686,6 @@ fn normalize_associated_type(&self,
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 @@ fn check_struct_fields_on_error(&self,
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 @@ fn check_expr_struct(&self,
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 @@ fn check_expr_kind(&self,
}
}
err.emit();
self.tcx().types.err
self.tcx.types.err
}
}
}
......@@ -3815,29 +3789,26 @@ fn check_expr_kind(&self,
// 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 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
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 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
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 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
};
// 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 @@ pub fn instantiate_value_path(&self,
// 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
......
......@@ -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
......
......@@ -15,6 +15,6 @@
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`
}
}
......@@ -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
}
......@@ -14,5 +14,6 @@
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`
}
......@@ -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
}
......
......@@ -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`
}
......@@ -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`
}
}
......@@ -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`
}
......@@ -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`
}
......@@ -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`
};
}
......@@ -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`
}
}
......@@ -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 {
......
......@@ -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
}
// 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
}
}
......@@ -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`
}
......@@ -51,4 +51,7 @@ fn main() {
if let None::<u8> = Some(8) {
panic!();
}
if let None::<u8> { .. } = Some(8) {
panic!();
}
}
......@@ -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;
}
fn f<T: Tr>() {
match S {
T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant
}
impl Tr for u8 {
type A = S<u8, u16>;
}
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>();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册