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.
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);
}
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)
}
}
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};
}
}
+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 {
})
}
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.
}
}
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);
+ }
}
}
```
"##,
-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.
// 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
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
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,
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,
}
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);
}
_ => {}
}
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);
}
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: {:?}",
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();
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);
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={:?}, \
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.
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 {
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 {
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());
}
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
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,
}
}
err.emit();
- self.tcx().types.err
+ self.tcx.types.err
}
}
}
// 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.
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)
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();
};
// 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))
}
}
// 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
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
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`
}
}
// 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
}
+++ /dev/null
-// 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.
-
-fn main () {
- let x = Foo { x: 1, y: 2 };
- //~^ ERROR E0422
- //~| NOTE not a structure
-}
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`
}
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
}
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`
}
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`
}
}
}
fn main() {
- E { name: "foobar" }; //~ ERROR `E` does not name a structure
+ E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
}
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`
}
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`
};
}
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`
}
}
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 {
+++ /dev/null
-// 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>() {
- 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 main() {
- match S {
- S::A {} => {} //~ ERROR ambiguous associated type
- }
-}
--- /dev/null
+// 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.
+
+// 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
+}
--- /dev/null
+// 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
+ }
+}
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`
}
if let None::<u8> = Some(8) {
panic!();
}
+ if let None::<u8> { .. } = Some(8) {
+ panic!();
+ }
}
--- /dev/null
+// 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<T, U = u16> {
+ a: T,
+ b: U,
+}
+
+trait Tr {
+ type A;
+}
+impl Tr for u8 {
+ type A = S<u8, u16>;
+}
+
+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() {
+ f::<u8>();
+}