Rollup merge of #30320 - nrc:err-names, r=@nikomatsakis
We can now handle name resolution errors and get past type checking (if we're a bit lucky). This is the first step towards doing code completion for partial programs (we need error recovery in the parser and early access to save-analysis).
This commit is contained in:
commit
ee24bddfc5
@ -99,8 +99,9 @@ pub fn check_crate<'ast>(sess: &Session,
|
||||
ast_map: ast_map,
|
||||
discriminant_map: RefCell::new(NodeMap()),
|
||||
};
|
||||
krate.visit_all_items(&mut visitor);
|
||||
sess.abort_if_errors();
|
||||
sess.abort_if_new_errors(|| {
|
||||
krate.visit_all_items(&mut visitor);
|
||||
});
|
||||
}
|
||||
|
||||
struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
|
||||
|
@ -52,6 +52,7 @@ pub enum Def {
|
||||
DefStruct(DefId),
|
||||
DefLabel(ast::NodeId),
|
||||
DefMethod(DefId),
|
||||
DefErr,
|
||||
}
|
||||
|
||||
/// The result of resolving a path.
|
||||
@ -124,7 +125,7 @@ impl Def {
|
||||
DefVariant(..) | DefTy(..) | DefAssociatedTy(..) |
|
||||
DefTyParam(..) | DefUse(..) | DefStruct(..) | DefTrait(..) |
|
||||
DefMethod(..) | DefConst(..) | DefAssociatedConst(..) |
|
||||
DefPrimTy(..) | DefLabel(..) | DefSelfTy(..) => {
|
||||
DefPrimTy(..) | DefLabel(..) | DefSelfTy(..) | DefErr => {
|
||||
panic!("attempted .def_id() on invalid {:?}", self)
|
||||
}
|
||||
}
|
||||
@ -142,7 +143,8 @@ impl Def {
|
||||
|
||||
DefLabel(..) |
|
||||
DefPrimTy(..) |
|
||||
DefSelfTy(..) => {
|
||||
DefSelfTy(..) |
|
||||
DefErr => {
|
||||
panic!("attempted .def_id() on invalid def: {:?}", self)
|
||||
}
|
||||
}
|
||||
|
@ -609,6 +609,8 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
|
||||
note: NoteNone
|
||||
}))
|
||||
}
|
||||
|
||||
def::DefErr => panic!("DefErr in memory categorization")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1196,7 +1198,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
|
||||
(*op)(self, cmt.clone(), pat);
|
||||
|
||||
let opt_def = if let Some(path_res) = self.tcx().def_map.borrow().get(&pat.id) {
|
||||
if path_res.depth != 0 {
|
||||
if path_res.depth != 0 || path_res.base_def == def::DefErr {
|
||||
// Since patterns can be associated constants
|
||||
// which are resolved during typeck, we might have
|
||||
// some unresolved patterns reaching this stage
|
||||
@ -1261,7 +1263,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
|
||||
_ => {
|
||||
self.tcx().sess.span_bug(
|
||||
pat.span,
|
||||
"enum pattern didn't resolve to enum or struct");
|
||||
&format!("enum pattern didn't resolve to enum or struct {:?}", opt_def));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,15 +95,16 @@ static ROOT_SCOPE: ScopeChain<'static> = RootScope;
|
||||
|
||||
pub fn krate(sess: &Session, krate: &hir::Crate, def_map: &DefMap) -> NamedRegionMap {
|
||||
let mut named_region_map = NodeMap();
|
||||
krate.visit_all_items(&mut LifetimeContext {
|
||||
sess: sess,
|
||||
named_region_map: &mut named_region_map,
|
||||
scope: &ROOT_SCOPE,
|
||||
def_map: def_map,
|
||||
trait_ref_hack: false,
|
||||
labels_in_fn: vec![],
|
||||
sess.abort_if_new_errors(|| {
|
||||
krate.visit_all_items(&mut LifetimeContext {
|
||||
sess: sess,
|
||||
named_region_map: &mut named_region_map,
|
||||
scope: &ROOT_SCOPE,
|
||||
def_map: def_map,
|
||||
trait_ref_hack: false,
|
||||
labels_in_fn: vec![],
|
||||
});
|
||||
});
|
||||
sess.abort_if_errors();
|
||||
named_region_map
|
||||
}
|
||||
|
||||
|
@ -2100,9 +2100,8 @@ impl<'tcx> ctxt<'tcx> {
|
||||
}) => {
|
||||
true
|
||||
}
|
||||
|
||||
Some(&def::PathResolution { base_def: def::DefErr, .. })=> true,
|
||||
Some(..) => false,
|
||||
|
||||
None => self.sess.span_bug(expr.span, &format!(
|
||||
"no def for path {}", expr.id))
|
||||
}
|
||||
|
@ -156,6 +156,15 @@ impl Session {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
pub fn abort_if_new_errors<F>(&self, mut f: F)
|
||||
where F: FnMut()
|
||||
{
|
||||
let count = self.err_count();
|
||||
f();
|
||||
if self.err_count() > count {
|
||||
self.abort_if_errors();
|
||||
}
|
||||
}
|
||||
pub fn span_warn(&self, sp: Span, msg: &str) {
|
||||
if self.can_print_warnings {
|
||||
self.diagnostic().span_warn(sp, msg)
|
||||
|
@ -407,7 +407,8 @@ impl tr for def::Def {
|
||||
def::DefUpvar(did1, nid1, index, nid2)
|
||||
}
|
||||
def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
|
||||
def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
|
||||
def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid)),
|
||||
def::DefErr => def::DefErr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -709,7 +709,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
DefUse(..) |
|
||||
DefUpvar(..) |
|
||||
DefLabel(..) |
|
||||
DefSelfTy(..) => {
|
||||
DefSelfTy(..) |
|
||||
DefErr => {
|
||||
panic!("didn't expect `{:?}`", def);
|
||||
}
|
||||
}
|
||||
|
@ -566,6 +566,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
|
||||
Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
|
||||
Err(_) => {
|
||||
// error already reported
|
||||
self.record_def(tref.trait_ref.ref_id, err_path_resolution())
|
||||
}
|
||||
}
|
||||
intravisit::walk_poly_trait_ref(self, tref, m);
|
||||
@ -2005,6 +2006,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
prefix.span,
|
||||
ResolutionError::FailedToResolve(
|
||||
&path_names_to_string(prefix, 0)));
|
||||
self.record_def(item.id, err_path_resolution());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2164,6 +2166,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
resolve_error(self,
|
||||
eq_pred.span,
|
||||
ResolutionError::UndeclaredAssociatedType);
|
||||
self.record_def(eq_pred.id, err_path_resolution());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2194,6 +2197,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
self.record_def(trait_ref.ref_id, path_res);
|
||||
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
|
||||
new_id = Some(path_res.base_def.def_id());
|
||||
} else {
|
||||
self.record_def(trait_ref.ref_id, err_path_resolution());
|
||||
}
|
||||
intravisit::walk_trait_ref(self, trait_ref);
|
||||
}
|
||||
@ -2463,6 +2468,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
self.record_def(ty.id, def);
|
||||
}
|
||||
None => {
|
||||
self.record_def(ty.id, err_path_resolution());
|
||||
|
||||
// Keep reporting some errors even if they're ignored above.
|
||||
self.resolve_path(ty.id, path, 0, TypeNS, true);
|
||||
|
||||
@ -2545,6 +2552,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(
|
||||
renamed)
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
FoundConst(def, lp, _) if const_ok => {
|
||||
debug!("(resolving pattern) resolving `{}` to constant", renamed);
|
||||
@ -2564,6 +2572,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(),
|
||||
name)
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
BareIdentifierPatternUnresolved => {
|
||||
debug!("(resolving pattern) binding `{}`", renamed);
|
||||
@ -2647,6 +2656,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
resolve_error(&self,
|
||||
path.span,
|
||||
ResolutionError::StaticVariableReference);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
_ => {
|
||||
// If anything ends up here entirely resolved,
|
||||
@ -2665,6 +2675,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
.name
|
||||
.as_str())
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
} else {
|
||||
let const_name = path.segments
|
||||
.last()
|
||||
@ -2684,6 +2695,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ResolutionError::UnresolvedEnumVariantStructOrConst(
|
||||
&path.segments.last().unwrap().identifier.name.as_str())
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
intravisit::walk_path(self, path);
|
||||
}
|
||||
@ -2726,6 +2738,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
&path.segments.last().unwrap().identifier.name.as_str()
|
||||
)
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -2737,6 +2750,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
.identifier
|
||||
.name
|
||||
.as_str()));
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
intravisit::walk_pat(self, pattern);
|
||||
}
|
||||
@ -2754,6 +2768,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ResolutionError::DoesNotNameAStruct(
|
||||
&*path_names_to_string(path, 0))
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
}
|
||||
intravisit::walk_path(self, path);
|
||||
@ -3430,6 +3445,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
} else {
|
||||
self.session.span_help(expr.span, &msg);
|
||||
}
|
||||
self.record_def(expr.id, err_path_resolution());
|
||||
} else {
|
||||
// Write the result into the def map.
|
||||
debug!("(resolving expr) resolved `{}`",
|
||||
@ -3454,6 +3470,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
let type_res = self.with_no_errors(|this| {
|
||||
this.resolve_path(expr.id, path, 0, TypeNS, false)
|
||||
});
|
||||
|
||||
self.record_def(expr.id, err_path_resolution());
|
||||
match type_res.map(|r| r.base_def) {
|
||||
Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => {
|
||||
resolve_error(
|
||||
@ -3540,6 +3558,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ResolutionError::DoesNotNameAStruct(
|
||||
&*path_names_to_string(path, 0))
|
||||
);
|
||||
self.record_def(expr.id, err_path_resolution());
|
||||
}
|
||||
}
|
||||
|
||||
@ -3562,6 +3581,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
|
||||
match self.search_label(label.node.name) {
|
||||
None => {
|
||||
self.record_def(expr.id, err_path_resolution());
|
||||
resolve_error(self,
|
||||
label.span,
|
||||
ResolutionError::UndeclaredLabel(&label.node.name.as_str()))
|
||||
@ -3811,6 +3831,14 @@ fn module_to_string(module: &Module) -> String {
|
||||
names_to_string(&names.into_iter().rev().collect::<Vec<ast::Name>>())
|
||||
}
|
||||
|
||||
fn err_path_resolution() -> PathResolution {
|
||||
PathResolution {
|
||||
base_def: DefErr,
|
||||
last_private: LastMod(AllPublic),
|
||||
depth: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct CrateMap {
|
||||
pub def_map: RefCell<DefMap>,
|
||||
@ -3836,7 +3864,6 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
|
||||
let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, None);
|
||||
|
||||
resolver.resolve_crate(krate);
|
||||
session.abort_if_errors();
|
||||
|
||||
check_unused::check_crate(&mut resolver, krate);
|
||||
|
||||
|
@ -276,7 +276,8 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
def::DefTyParam(..) |
|
||||
def::DefUse(_) |
|
||||
def::DefMethod(..) |
|
||||
def::DefPrimTy(_) => {
|
||||
def::DefPrimTy(_) |
|
||||
def::DefErr => {
|
||||
self.sess.span_bug(span,
|
||||
&format!("lookup_def_kind for unexpected item: {:?}", def));
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
|
||||
def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
|
||||
def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
|
||||
def::DefUse(..) | def::DefLabel(..) | def::DefTyParam(..) |
|
||||
def::DefSelfTy(..) => {
|
||||
def::DefSelfTy(..) | def::DefErr => {
|
||||
bcx.tcx().sess.span_bug(
|
||||
ref_expr.span,
|
||||
&format!("cannot translate def {:?} \
|
||||
|
@ -719,6 +719,9 @@ fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &hir::TraitRef) -> DefId
|
||||
let path = &trait_ref.path;
|
||||
match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
|
||||
def::DefTrait(trait_def_id) => trait_def_id,
|
||||
def::DefErr => {
|
||||
this.tcx().sess.fatal("cannot continue compilation due to previous error");
|
||||
}
|
||||
_ => {
|
||||
span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
|
||||
path);
|
||||
@ -1533,6 +1536,9 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
def::DefPrimTy(prim_ty) => {
|
||||
prim_ty_to_ty(tcx, base_segments, prim_ty)
|
||||
}
|
||||
def::DefErr => {
|
||||
return this.tcx().types.err;
|
||||
}
|
||||
_ => {
|
||||
let id_node = tcx.map.as_local_node_id(def.def_id()).unwrap();
|
||||
span_err!(tcx.sess, span, E0248,
|
||||
|
@ -142,20 +142,24 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
return;
|
||||
}
|
||||
}
|
||||
let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
|
||||
let const_scheme = tcx.lookup_item_type(const_did);
|
||||
assert!(const_scheme.generics.is_empty());
|
||||
let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
|
||||
&Substs::empty(),
|
||||
&const_scheme.ty);
|
||||
fcx.write_ty(pat.id, const_ty);
|
||||
if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) {
|
||||
let const_did = pat_def.def_id();
|
||||
let const_scheme = tcx.lookup_item_type(const_did);
|
||||
assert!(const_scheme.generics.is_empty());
|
||||
let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
|
||||
&Substs::empty(),
|
||||
&const_scheme.ty);
|
||||
fcx.write_ty(pat.id, const_ty);
|
||||
|
||||
// FIXME(#20489) -- we should limit the types here to scalars or something!
|
||||
// FIXME(#20489) -- we should limit the types here to scalars or something!
|
||||
|
||||
// As with PatLit, what we really want here is that there
|
||||
// exist a LUB, but for the cases that can occur, subtype
|
||||
// is good enough.
|
||||
demand::suptype(fcx, pat.span, expected, const_ty);
|
||||
// As with PatLit, what we really want here is that there
|
||||
// exist a LUB, but for the cases that can occur, subtype
|
||||
// is good enough.
|
||||
demand::suptype(fcx, pat.span, expected, const_ty);
|
||||
} else {
|
||||
fcx.write_error(pat.id);
|
||||
}
|
||||
}
|
||||
hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => {
|
||||
let typ = fcx.local_ty(pat.span, pat.id);
|
||||
@ -186,14 +190,15 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
|
||||
// if there are multiple arms, make sure they all agree on
|
||||
// what the type of the binding `x` ought to be
|
||||
let canon_id = *pcx.map.get(&path.node.name).unwrap();
|
||||
if canon_id != pat.id {
|
||||
let ct = fcx.local_ty(pat.span, canon_id);
|
||||
demand::eqtype(fcx, pat.span, ct, typ);
|
||||
}
|
||||
if let Some(&canon_id) = pcx.map.get(&path.node.name) {
|
||||
if canon_id != pat.id {
|
||||
let ct = fcx.local_ty(pat.span, canon_id);
|
||||
demand::eqtype(fcx, pat.span, ct, typ);
|
||||
}
|
||||
|
||||
if let Some(ref p) = *sub {
|
||||
check_pat(pcx, &**p, expected);
|
||||
if let Some(ref p) = *sub {
|
||||
check_pat(pcx, &**p, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::PatIdent(_, ref path, _) => {
|
||||
@ -208,6 +213,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
hir::PatQPath(ref qself, ref path) => {
|
||||
let self_ty = fcx.to_ty(&qself.ty);
|
||||
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
|
||||
if d.base_def == def::DefErr {
|
||||
fcx.write_error(pat.id);
|
||||
return;
|
||||
}
|
||||
d
|
||||
} else if qself.position == 0 {
|
||||
// This is just a sentinel for finish_resolving_def_to_ty.
|
||||
@ -218,8 +227,9 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
depth: path.segments.len()
|
||||
}
|
||||
} else {
|
||||
tcx.sess.span_bug(pat.span,
|
||||
&format!("unbound path {:?}", pat))
|
||||
debug!("unbound path {:?}", pat);
|
||||
fcx.write_error(pat.id);
|
||||
return;
|
||||
};
|
||||
if let Some((opt_ty, segments, def)) =
|
||||
resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty),
|
||||
@ -597,7 +607,20 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
let fcx = pcx.fcx;
|
||||
let tcx = pcx.fcx.ccx.tcx;
|
||||
|
||||
let path_res = *tcx.def_map.borrow().get(&pat.id).unwrap();
|
||||
let path_res = match tcx.def_map.borrow().get(&pat.id) {
|
||||
Some(&path_res) if path_res.base_def != def::DefErr => path_res,
|
||||
_ => {
|
||||
fcx.write_error(pat.id);
|
||||
|
||||
if let Some(subpats) = subpats {
|
||||
for pat in subpats {
|
||||
check_pat(pcx, &**pat, tcx.types.err);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(fcx, path_res,
|
||||
None, path,
|
||||
@ -636,7 +659,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
let report_bad_struct_kind = |is_warning| {
|
||||
bad_struct_kind_err(tcx.sess, pat.span, path, is_warning);
|
||||
if is_warning {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
fcx.write_error(pat.id);
|
||||
|
@ -26,6 +26,7 @@ use super::write_call;
|
||||
|
||||
use CrateCtxt;
|
||||
use middle::cstore::LOCAL_CRATE;
|
||||
use middle::def;
|
||||
use middle::def_id::DefId;
|
||||
use middle::infer;
|
||||
use middle::ty::{self, LvaluePreference, Ty};
|
||||
@ -234,7 +235,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
|
||||
if let hir::ExprCall(ref expr, _) = call_expr.node {
|
||||
let tcx = fcx.tcx();
|
||||
if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
|
||||
if pr.depth == 0 {
|
||||
if pr.depth == 0 && pr.base_def != def::DefErr {
|
||||
if let Some(span) = tcx.map.span_if_local(pr.def_id()) {
|
||||
tcx.sess.span_note(span, "defined here")
|
||||
}
|
||||
|
@ -385,61 +385,60 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn check_wf_old(ccx: &CrateCtxt) {
|
||||
// FIXME(#25759). The new code below is much more reliable but (for now)
|
||||
// only generates warnings. So as to ensure that we continue
|
||||
// getting errors where we used to get errors, we run the old wf
|
||||
// code first and abort if it encounters any errors. If no abort
|
||||
// comes, we run the new code and issue warnings.
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
|
||||
krate.visit_all_items(&mut visit);
|
||||
|
||||
// If types are not well-formed, it leads to all manner of errors
|
||||
// downstream, so stop reporting errors at this point.
|
||||
ccx.tcx.sess.abort_if_errors();
|
||||
ccx.tcx.sess.abort_if_new_errors(|| {
|
||||
// FIXME(#25759). The new code below is much more reliable but (for now)
|
||||
// only generates warnings. So as to ensure that we continue
|
||||
// getting errors where we used to get errors, we run the old wf
|
||||
// code first and abort if it encounters any errors. If no abort
|
||||
// comes, we run the new code and issue warnings.
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
|
||||
krate.visit_all_items(&mut visit);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn check_wf_new(ccx: &CrateCtxt) {
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx);
|
||||
krate.visit_all_items(&mut visit);
|
||||
|
||||
// If types are not well-formed, it leads to all manner of errors
|
||||
// downstream, so stop reporting errors at this point.
|
||||
ccx.tcx.sess.abort_if_errors();
|
||||
ccx.tcx.sess.abort_if_new_errors(|| {
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx);
|
||||
krate.visit_all_items(&mut visit);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn check_item_types(ccx: &CrateCtxt) {
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = CheckItemTypesVisitor { ccx: ccx };
|
||||
krate.visit_all_items(&mut visit);
|
||||
ccx.tcx.sess.abort_if_errors();
|
||||
ccx.tcx.sess.abort_if_new_errors(|| {
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = CheckItemTypesVisitor { ccx: ccx };
|
||||
krate.visit_all_items(&mut visit);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn check_item_bodies(ccx: &CrateCtxt) {
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = CheckItemBodiesVisitor { ccx: ccx };
|
||||
krate.visit_all_items(&mut visit);
|
||||
|
||||
ccx.tcx.sess.abort_if_errors();
|
||||
ccx.tcx.sess.abort_if_new_errors(|| {
|
||||
let krate = ccx.tcx.map.krate();
|
||||
let mut visit = CheckItemBodiesVisitor { ccx: ccx };
|
||||
krate.visit_all_items(&mut visit);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn check_drop_impls(ccx: &CrateCtxt) {
|
||||
let drop_trait = match ccx.tcx.lang_items.drop_trait() {
|
||||
Some(id) => ccx.tcx.lookup_trait_def(id), None => { return }
|
||||
};
|
||||
drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| {
|
||||
if drop_impl_did.is_local() {
|
||||
match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
|
||||
Ok(()) => {}
|
||||
Err(()) => {
|
||||
assert!(ccx.tcx.sess.has_errors());
|
||||
ccx.tcx.sess.abort_if_new_errors(|| {
|
||||
let drop_trait = match ccx.tcx.lang_items.drop_trait() {
|
||||
Some(id) => ccx.tcx.lookup_trait_def(id), None => { return }
|
||||
};
|
||||
drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| {
|
||||
if drop_impl_did.is_local() {
|
||||
match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
|
||||
Ok(()) => {}
|
||||
Err(()) => {
|
||||
assert!(ccx.tcx.sess.has_errors());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ccx.tcx.sess.abort_if_errors();
|
||||
}
|
||||
|
||||
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
@ -891,75 +890,71 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
for impl_item in impl_items {
|
||||
let ty_impl_item = ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(impl_item.id));
|
||||
let ty_trait_item = trait_items.iter()
|
||||
.find(|ac| ac.name() == ty_impl_item.name())
|
||||
.unwrap_or_else(|| {
|
||||
// This is checked by resolve
|
||||
tcx.sess.span_bug(impl_item.span,
|
||||
&format!("impl-item `{}` is not a member of `{:?}`",
|
||||
ty_impl_item.name(),
|
||||
impl_trait_ref));
|
||||
});
|
||||
match impl_item.node {
|
||||
hir::ImplItemKind::Const(..) => {
|
||||
let impl_const = match ty_impl_item {
|
||||
ty::ConstTraitItem(ref cti) => cti,
|
||||
_ => tcx.sess.span_bug(impl_item.span, "non-const impl-item for const")
|
||||
};
|
||||
.find(|ac| ac.name() == ty_impl_item.name());
|
||||
|
||||
// Find associated const definition.
|
||||
if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
|
||||
compare_const_impl(ccx.tcx,
|
||||
&impl_const,
|
||||
impl_item.span,
|
||||
trait_const,
|
||||
&*impl_trait_ref);
|
||||
} else {
|
||||
span_err!(tcx.sess, impl_item.span, E0323,
|
||||
"item `{}` is an associated const, \
|
||||
which doesn't match its trait `{:?}`",
|
||||
impl_const.name,
|
||||
impl_trait_ref)
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::Method(ref sig, ref body) => {
|
||||
check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
|
||||
if let Some(ty_trait_item) = ty_trait_item {
|
||||
match impl_item.node {
|
||||
hir::ImplItemKind::Const(..) => {
|
||||
let impl_const = match ty_impl_item {
|
||||
ty::ConstTraitItem(ref cti) => cti,
|
||||
_ => tcx.sess.span_bug(impl_item.span, "non-const impl-item for const")
|
||||
};
|
||||
|
||||
let impl_method = match ty_impl_item {
|
||||
ty::MethodTraitItem(ref mti) => mti,
|
||||
_ => tcx.sess.span_bug(impl_item.span, "non-method impl-item for method")
|
||||
};
|
||||
|
||||
if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
|
||||
compare_impl_method(ccx.tcx,
|
||||
&impl_method,
|
||||
impl_item.span,
|
||||
body.id,
|
||||
&trait_method,
|
||||
&impl_trait_ref);
|
||||
} else {
|
||||
span_err!(tcx.sess, impl_item.span, E0324,
|
||||
"item `{}` is an associated method, \
|
||||
which doesn't match its trait `{:?}`",
|
||||
impl_method.name,
|
||||
impl_trait_ref)
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => {
|
||||
let impl_type = match ty_impl_item {
|
||||
ty::TypeTraitItem(ref tti) => tti,
|
||||
_ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
|
||||
};
|
||||
|
||||
if let &ty::TypeTraitItem(ref at) = ty_trait_item {
|
||||
if let Some(_) = at.ty {
|
||||
overridden_associated_type = Some(impl_item);
|
||||
// Find associated const definition.
|
||||
if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
|
||||
compare_const_impl(ccx.tcx,
|
||||
&impl_const,
|
||||
impl_item.span,
|
||||
trait_const,
|
||||
&*impl_trait_ref);
|
||||
} else {
|
||||
span_err!(tcx.sess, impl_item.span, E0323,
|
||||
"item `{}` is an associated const, \
|
||||
which doesn't match its trait `{:?}`",
|
||||
impl_const.name,
|
||||
impl_trait_ref)
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::Method(ref sig, ref body) => {
|
||||
check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
|
||||
|
||||
let impl_method = match ty_impl_item {
|
||||
ty::MethodTraitItem(ref mti) => mti,
|
||||
_ => tcx.sess.span_bug(impl_item.span, "non-method impl-item for method")
|
||||
};
|
||||
|
||||
if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
|
||||
compare_impl_method(ccx.tcx,
|
||||
&impl_method,
|
||||
impl_item.span,
|
||||
body.id,
|
||||
&trait_method,
|
||||
&impl_trait_ref);
|
||||
} else {
|
||||
span_err!(tcx.sess, impl_item.span, E0324,
|
||||
"item `{}` is an associated method, \
|
||||
which doesn't match its trait `{:?}`",
|
||||
impl_method.name,
|
||||
impl_trait_ref)
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => {
|
||||
let impl_type = match ty_impl_item {
|
||||
ty::TypeTraitItem(ref tti) => tti,
|
||||
_ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
|
||||
};
|
||||
|
||||
if let &ty::TypeTraitItem(ref at) = ty_trait_item {
|
||||
if let Some(_) = at.ty {
|
||||
overridden_associated_type = Some(impl_item);
|
||||
}
|
||||
} else {
|
||||
span_err!(tcx.sess, impl_item.span, E0325,
|
||||
"item `{}` is an associated type, \
|
||||
which doesn't match its trait `{:?}`",
|
||||
impl_type.name,
|
||||
impl_trait_ref)
|
||||
}
|
||||
} else {
|
||||
span_err!(tcx.sess, impl_item.span, E0325,
|
||||
"item `{}` is an associated type, \
|
||||
which doesn't match its trait `{:?}`",
|
||||
impl_type.name,
|
||||
impl_trait_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3193,6 +3188,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
|
||||
// Find the relevant variant
|
||||
let def = lookup_full_def(tcx, path.span, expr.id);
|
||||
if def == def::DefErr {
|
||||
check_struct_fields_on_error(fcx, expr.id, fields, base_expr);
|
||||
return;
|
||||
}
|
||||
let (adt, variant) = match fcx.def_struct_variant(def, path.span) {
|
||||
Some((adt, variant)) => (adt, variant),
|
||||
None => {
|
||||
@ -3371,17 +3370,21 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
if let Some((opt_ty, segments, def)) =
|
||||
resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
|
||||
expr.span, expr.id) {
|
||||
let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
|
||||
expr.span,
|
||||
def);
|
||||
instantiate_path(fcx,
|
||||
segments,
|
||||
scheme,
|
||||
&predicates,
|
||||
opt_ty,
|
||||
def,
|
||||
expr.span,
|
||||
id);
|
||||
if def != def::DefErr {
|
||||
let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
|
||||
expr.span,
|
||||
def);
|
||||
instantiate_path(fcx,
|
||||
segments,
|
||||
scheme,
|
||||
&predicates,
|
||||
opt_ty,
|
||||
def,
|
||||
expr.span,
|
||||
id);
|
||||
} else {
|
||||
fcx.write_ty(id, fcx.tcx().types.err);
|
||||
}
|
||||
}
|
||||
|
||||
// We always require that the type provided as the value for
|
||||
@ -4326,7 +4329,8 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
def::DefForeignMod(..) |
|
||||
def::DefUse(..) |
|
||||
def::DefLabel(..) |
|
||||
def::DefSelfTy(..) => {
|
||||
def::DefSelfTy(..) |
|
||||
def::DefErr => {
|
||||
fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
|
||||
}
|
||||
}
|
||||
@ -4496,7 +4500,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
def::DefLocal(..) |
|
||||
def::DefUse(..) |
|
||||
def::DefLabel(..) |
|
||||
def::DefUpvar(..) => {
|
||||
def::DefUpvar(..) |
|
||||
def::DefErr => {
|
||||
segment_spaces = vec![None; segments.len()];
|
||||
}
|
||||
}
|
||||
|
@ -122,10 +122,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
} else {
|
||||
let tcx = self.tcx();
|
||||
|
||||
if let hir::ExprAssignOp(..) = e.node {
|
||||
if let hir::ExprAssignOp(_, ref lhs, ref rhs) = e.node {
|
||||
if
|
||||
!tcx.sess.features.borrow().augmented_assignments &&
|
||||
!self.fcx.expr_ty(e).references_error()
|
||||
!self.fcx.expr_ty(e).references_error() &&
|
||||
!self.fcx.expr_ty(lhs).references_error() &&
|
||||
!self.fcx.expr_ty(rhs).references_error()
|
||||
{
|
||||
tcx.sess.span_err(
|
||||
e.span,
|
||||
|
@ -205,6 +205,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||
"f64",
|
||||
item.span);
|
||||
}
|
||||
ty::TyError => {
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
span_err!(self.tcx.sess, item.span, E0118,
|
||||
"no base type found for inherent implementation; \
|
||||
|
@ -331,18 +331,21 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
|
||||
tcx: tcx
|
||||
};
|
||||
|
||||
time(time_passes, "type collecting", ||
|
||||
collect::collect_item_types(tcx));
|
||||
|
||||
// this ensures that later parts of type checking can assume that items
|
||||
// have valid types and not error
|
||||
tcx.sess.abort_if_errors();
|
||||
tcx.sess.abort_if_new_errors(|| {
|
||||
time(time_passes, "type collecting", ||
|
||||
collect::collect_item_types(tcx));
|
||||
|
||||
});
|
||||
|
||||
time(time_passes, "variance inference", ||
|
||||
variance::infer_variance(tcx));
|
||||
|
||||
time(time_passes, "coherence checking", ||
|
||||
coherence::check_coherence(&ccx));
|
||||
tcx.sess.abort_if_new_errors(|| {
|
||||
time(time_passes, "coherence checking", ||
|
||||
coherence::check_coherence(&ccx));
|
||||
});
|
||||
|
||||
time(time_passes, "wf checking (old)", ||
|
||||
check::check_wf_old(&ccx));
|
||||
|
@ -23,7 +23,8 @@ fn main() {
|
||||
let ps = syntax::parse::ParseSess::new();
|
||||
let mut cx = syntax::ext::base::ExtCtxt::new(
|
||||
&ps, vec![],
|
||||
syntax::ext::expand::ExpansionConfig::default("qquote".to_string()));
|
||||
syntax::ext::expand::ExpansionConfig::default("qquote".to_string()),
|
||||
&mut Vec::new());
|
||||
cx.bt_push(syntax::codemap::ExpnInfo {
|
||||
call_site: DUMMY_SP,
|
||||
callee: syntax::codemap::NameAndSpan {
|
||||
|
@ -32,13 +32,13 @@ impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
|
||||
impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
|
||||
//~^ ERROR E0119
|
||||
fn into_cow(self) -> Cow<'a, B> {
|
||||
Cow
|
||||
Cow(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
|
||||
fn into_cow(self) -> Cow<'a, B> {
|
||||
Cow
|
||||
Cow(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,14 +9,12 @@
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
// error-pattern: unresolved
|
||||
|
||||
enum color { rgb(isize, isize, isize), rgba(isize, isize, isize, isize), }
|
||||
|
||||
fn main() {
|
||||
let red: color = rgb(255, 0, 0);
|
||||
let red: color = color::rgb(255, 0, 0);
|
||||
match red {
|
||||
rgb(r, g, b) => { println!("rgb"); }
|
||||
hsl(h, s, l) => { println!("hsl"); }
|
||||
color::rgb(r, g, b) => { println!("rgb"); }
|
||||
color::hsl(h, s, l) => { println!("hsl"); } //~ ERROR no associated
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,9 @@
|
||||
|
||||
// If the trait is not object-safe, we give a more tailored message
|
||||
// because we're such schnuckels:
|
||||
trait NotObjectSafe { fn eq(&self, other: Self); }
|
||||
impl NotObjectSafe for NotObjectSafe { } //~ ERROR E0372
|
||||
trait NotObjectSafe { fn eq(&self, other: &Self); }
|
||||
impl NotObjectSafe for NotObjectSafe { //~ ERROR E0372
|
||||
fn eq(&self, other: &Self) { panic!(); }
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -28,8 +28,6 @@ impl Copy for MyType {}
|
||||
|
||||
impl Copy for &'static mut MyType {}
|
||||
//~^ ERROR E0206
|
||||
//~| ERROR E0277
|
||||
//~| ERROR E0277
|
||||
impl Clone for MyType { fn clone(&self) -> Self { *self } }
|
||||
|
||||
impl Copy for (MyType, MyType) {}
|
||||
@ -42,8 +40,6 @@ impl Copy for &'static NotSync {}
|
||||
impl Copy for [MyType] {}
|
||||
//~^ ERROR E0206
|
||||
//~| ERROR E0117
|
||||
//~| ERROR E0277
|
||||
//~| ERROR E0277
|
||||
|
||||
impl Copy for &'static [NotSync] {}
|
||||
//~^ ERROR E0206
|
||||
|
@ -30,7 +30,6 @@ impl Sized for (MyType, MyType) {} //~ ERROR E0117
|
||||
impl Sized for &'static NotSync {} //~ ERROR E0322
|
||||
|
||||
impl Sized for [MyType] {} //~ ERROR E0117
|
||||
//~^ ERROR E0277
|
||||
|
||||
impl Sized for &'static [NotSync] {} //~ ERROR E0117
|
||||
|
||||
|
@ -33,6 +33,7 @@ trait Qux<T,T> {}
|
||||
|
||||
impl<T,T> Qux<T,T> for Option<T> {}
|
||||
//~^ ERROR the name `T` is already used
|
||||
//~^^ ERROR the type parameter `T` is not constrained
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// see #9186
|
||||
|
||||
enum Bar<T> { What }
|
||||
enum Bar<T> { What } //~ ERROR parameter `T` is never used
|
||||
|
||||
fn foo<T>() {
|
||||
static a: Bar<T> = Bar::What;
|
||||
|
@ -9,8 +9,8 @@
|
||||
// except according to those terms.
|
||||
|
||||
trait Trait {
|
||||
fn outer(self) {
|
||||
fn inner(_: Self) {
|
||||
fn outer(&self) {
|
||||
fn inner(_: &Self) {
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of `Self` outside of an impl or trait
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
trait Foo {
|
||||
fn bar(&self);
|
||||
fn baz(&self) { }
|
||||
fn bah(_: Option<Self>) { }
|
||||
fn bah(_: Option<&Self>) { }
|
||||
}
|
||||
|
||||
struct BarTy {
|
||||
|
@ -14,7 +14,7 @@ trait From<Src> {
|
||||
fn from(src: Src) -> <Self as From<Src>>::Output;
|
||||
}
|
||||
|
||||
trait To {
|
||||
trait To: Sized {
|
||||
fn to<Dst: From<Self>>(self) ->
|
||||
<Dst as From<Self>>::Dst
|
||||
//~^ ERROR use of undeclared associated type `From::Dst`
|
||||
|
@ -62,7 +62,7 @@ fn usize<'usize>(usize: &'usize usize) -> &'usize usize { usize }
|
||||
fn main() {
|
||||
let bool = true;
|
||||
match bool {
|
||||
str @ true => if str { i32 as i64 } else { 0 },
|
||||
str @ true => if str { i32 as i64 } else { i64 },
|
||||
false => i64,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -13,5 +13,6 @@ pub trait ToNbt<T> {
|
||||
}
|
||||
|
||||
impl ToNbt<Self> {} //~ ERROR use of `Self` outside of an impl or trait
|
||||
//~^ WARNING the trait `ToNbt` cannot be made into an object
|
||||
|
||||
fn main() {}
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
trait Groom {
|
||||
fn shave();
|
||||
fn shave(other: usize);
|
||||
}
|
||||
|
||||
pub struct cat {
|
||||
@ -30,7 +30,7 @@ impl MaybeDog {
|
||||
}
|
||||
|
||||
impl Groom for cat {
|
||||
fn shave(&self, other: usize) {
|
||||
fn shave(other: usize) {
|
||||
whiskers -= other;
|
||||
//~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
|
||||
shave(4);
|
||||
|
@ -11,10 +11,12 @@
|
||||
// Make sure that label for continue and break is spanned correctly
|
||||
|
||||
fn main() {
|
||||
continue
|
||||
'b //~ ERROR use of undeclared label
|
||||
;
|
||||
break
|
||||
'c //~ ERROR use of undeclared label
|
||||
;
|
||||
loop {
|
||||
continue
|
||||
'b //~ ERROR use of undeclared label
|
||||
;
|
||||
break
|
||||
'c //~ ERROR use of undeclared label
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -13,13 +13,13 @@ trait siphash {
|
||||
fn reset(&self);
|
||||
}
|
||||
|
||||
fn siphash(k0 : u64, k1 : u64) -> siphash {
|
||||
fn siphash(k0 : u64, k1 : u64) {
|
||||
struct SipState {
|
||||
v0: u64,
|
||||
v1: u64,
|
||||
}
|
||||
|
||||
fn mk_result(st : SipState) -> u64 {
|
||||
fn mk_result(st : &SipState) -> u64 {
|
||||
|
||||
let v0 = st.v0;
|
||||
let v1 = st.v1;
|
||||
|
@ -12,7 +12,7 @@ trait SipHash {
|
||||
fn reset(&self);
|
||||
}
|
||||
|
||||
fn siphash(k0 : u64) -> SipHash {
|
||||
fn siphash(k0 : u64) {
|
||||
struct SipState {
|
||||
v0: u64,
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ fn foo<T>() {
|
||||
}
|
||||
|
||||
impl<T> Drop for foo<T> {
|
||||
//~^ ERROR wrong number of type arguments
|
||||
//~^^ ERROR the type parameter `T` is not constrained
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ fn main() {
|
||||
Bar = foo
|
||||
//~^ ERROR attempt to use a non-constant value in a constant
|
||||
//~| ERROR unresolved name `foo`
|
||||
//~^^^ ERROR constant evaluation error: non-constant path in constant expression
|
||||
}
|
||||
|
||||
println!("{}", Stuff::Bar);
|
||||
|
@ -30,5 +30,7 @@ impl ToString_ for Point {
|
||||
|
||||
fn main() {
|
||||
let p = Point::new(0.0, 0.0);
|
||||
//~^ ERROR no associated item named `new` found for type `Point` in the current scope
|
||||
println!("{}", p.to_string());
|
||||
//~^ ERROR the type of this value must be known in this context
|
||||
}
|
||||
|
@ -9,12 +9,10 @@
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
|
||||
// error-pattern:unresolved enum variant
|
||||
|
||||
fn main() {
|
||||
let z = match 3 {
|
||||
x(1) => x(1)
|
||||
x(1) => x(1) //~ ERROR unresolved enum variant
|
||||
//~^ ERROR unresolved name `x`
|
||||
};
|
||||
assert_eq!(z,3);
|
||||
assert!(z == 3);
|
||||
}
|
||||
|
@ -13,4 +13,5 @@ struct A { foo: isize }
|
||||
fn main() {
|
||||
let A { foo, foo } = A { foo: 3 };
|
||||
//~^ ERROR: identifier `foo` is bound more than once in the same pattern
|
||||
//~^^ ERROR: field `foo` bound multiple times
|
||||
}
|
||||
|
@ -13,5 +13,5 @@
|
||||
mod mod_file_aux;
|
||||
|
||||
fn main() {
|
||||
assert_eq!(mod_file_aux::bar(), 10); //~ ERROR unresolved name
|
||||
assert!(mod_file_aux::bar() == 10); //~ ERROR unresolved name
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ struct IWantToCopyThis {
|
||||
|
||||
impl Copy for IWantToCopyThis {}
|
||||
//~^ ERROR the trait `Copy` may not be implemented for this type
|
||||
//~| ERROR E0277
|
||||
|
||||
enum CantCopyThisEither {
|
||||
A,
|
||||
@ -29,6 +28,5 @@ enum IWantToCopyThisToo {
|
||||
|
||||
impl Copy for IWantToCopyThisToo {}
|
||||
//~^ ERROR the trait `Copy` may not be implemented for this type
|
||||
//~| ERROR E0277
|
||||
|
||||
fn main() {}
|
||||
|
@ -16,6 +16,7 @@ fn matcher1(x: opts) {
|
||||
match x {
|
||||
opts::a(ref i) | opts::b(i) => {}
|
||||
//~^ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1
|
||||
//~^^ ERROR mismatched types
|
||||
opts::c(_) => {}
|
||||
}
|
||||
}
|
||||
@ -24,6 +25,7 @@ fn matcher2(x: opts) {
|
||||
match x {
|
||||
opts::a(ref i) | opts::b(i) => {}
|
||||
//~^ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1
|
||||
//~^^ ERROR mismatched types
|
||||
opts::c(_) => {}
|
||||
}
|
||||
}
|
||||
@ -32,6 +34,7 @@ fn matcher4(x: opts) {
|
||||
match x {
|
||||
opts::a(ref mut i) | opts::b(ref i) => {}
|
||||
//~^ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1
|
||||
//~^^ ERROR mismatched types
|
||||
opts::c(_) => {}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
trait TraitA<A> {
|
||||
fn outer(self) {
|
||||
enum Foo<B> {
|
||||
//~^ ERROR parameter `B` is never used
|
||||
Variance(A)
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of undeclared type name `A`
|
||||
@ -27,6 +28,7 @@ trait TraitB<A> {
|
||||
struct Foo<B>(A);
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of undeclared type name `A`
|
||||
//~^^^ ERROR parameter `B` is never used
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +37,7 @@ trait TraitC<A> {
|
||||
struct Foo<B> { a: A }
|
||||
//~^ ERROR can't use type parameters from outer function
|
||||
//~^^ ERROR use of undeclared type name `A`
|
||||
//~^^^ ERROR parameter `B` is never used
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
pub fn main() {
|
||||
let asdf_fdsa = "<.<".to_string();
|
||||
assert_eq!(concat_idents!(asd, f_f, dsa), "<.<".to_string());
|
||||
assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
|
||||
//~^ ERROR: unresolved name `asdf_fdsa`
|
||||
|
||||
assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction");
|
||||
|
@ -18,7 +18,7 @@ extern crate trait_safety_lib as lib;
|
||||
struct Bar;
|
||||
impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration
|
||||
fn foo(&self) -> isize {
|
||||
*self as isize
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,11 @@
|
||||
// impls cannot be unsafe.
|
||||
|
||||
trait SafeTrait {
|
||||
fn foo(self) { }
|
||||
fn foo(&self) { }
|
||||
}
|
||||
|
||||
unsafe trait UnsafeTrait {
|
||||
fn foo(self) { }
|
||||
fn foo(&self) { }
|
||||
}
|
||||
|
||||
unsafe impl UnsafeTrait for u8 { } // OK
|
||||
|
Loading…
x
Reference in New Issue
Block a user