From 7e0c3de4c473c3779046951abec46517fdba8cc9 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 18 Feb 2017 22:48:36 -0500 Subject: [PATCH 01/22] Remove `else`, unindent. --- src/librustc/traits/error_reporting.rs | 219 ++++++++++++------------- 1 file changed, 109 insertions(+), 110 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 70ca5fe83a932..411e986f62d90 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -525,127 +525,126 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { lint_id) .emit(); return; - } else { - match obligation.predicate { - ty::Predicate::Trait(ref trait_predicate) => { - let trait_predicate = - self.resolve_type_vars_if_possible(trait_predicate); + } + match obligation.predicate { + ty::Predicate::Trait(ref trait_predicate) => { + let trait_predicate = + self.resolve_type_vars_if_possible(trait_predicate); - if self.tcx.sess.has_errors() && trait_predicate.references_error() { - return; + if self.tcx.sess.has_errors() && trait_predicate.references_error() { + return; + } else { + let trait_ref = trait_predicate.to_poly_trait_ref(); + let (post_message, pre_message) = match self.get_parent_trait_ref( + &obligation.cause.code) + { + Some(t) => { + (format!(" in `{}`", t), format!("within `{}`, ", t)) + } + None => (String::new(), String::new()), + }; + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0277, + "the trait bound `{}` is not satisfied{}", + trait_ref.to_predicate(), + post_message); + err.span_label(span, + &format!("{}the trait `{}` is not \ + implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty())); + + // Try to report a help message + + if !trait_ref.has_infer_types() && + self.predicate_can_apply(trait_ref) { + // If a where-clause may be useful, remind the + // user that they can add it. + // + // don't display an on-unimplemented note, as + // these notes will often be of the form + // "the type `T` can't be frobnicated" + // which is somewhat confusing. + err.help(&format!("consider adding a `where {}` bound", + trait_ref.to_predicate())); + } else if let Some(s) = self.on_unimplemented_note(trait_ref, + obligation) { + // If it has a custom "#[rustc_on_unimplemented]" + // error message, let's display it! + err.note(&s); } else { - let trait_ref = trait_predicate.to_poly_trait_ref(); - let (post_message, pre_message) = match self.get_parent_trait_ref( - &obligation.cause.code) - { - Some(t) => { - (format!(" in `{}`", t), format!("within `{}`, ", t)) - } - None => (String::new(), String::new()), - }; - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0277, - "the trait bound `{}` is not satisfied{}", - trait_ref.to_predicate(), - post_message); - err.span_label(span, - &format!("{}the trait `{}` is not \ - implemented for `{}`", - pre_message, - trait_ref, - trait_ref.self_ty())); - - // Try to report a help message - - if !trait_ref.has_infer_types() && - self.predicate_can_apply(trait_ref) { - // If a where-clause may be useful, remind the - // user that they can add it. - // - // don't display an on-unimplemented note, as - // these notes will often be of the form - // "the type `T` can't be frobnicated" - // which is somewhat confusing. - err.help(&format!("consider adding a `where {}` bound", - trait_ref.to_predicate())); - } else if let Some(s) = self.on_unimplemented_note(trait_ref, - obligation) { - // If it has a custom "#[rustc_on_unimplemented]" - // error message, let's display it! - err.note(&s); - } else { - // If we can't show anything useful, try to find - // similar impls. - let impl_candidates = - self.find_similar_impl_candidates(trait_ref); - if impl_candidates.len() > 0 { - self.report_similar_impl_candidates(trait_ref, &mut err); - } + // If we can't show anything useful, try to find + // similar impls. + let impl_candidates = + self.find_similar_impl_candidates(trait_ref); + if impl_candidates.len() > 0 { + self.report_similar_impl_candidates(trait_ref, &mut err); } - err } + err } + } - ty::Predicate::Equate(ref predicate) => { - let predicate = self.resolve_type_vars_if_possible(predicate); - let err = self.equality_predicate(&obligation.cause, - &predicate).err().unwrap(); - struct_span_err!(self.tcx.sess, span, E0278, - "the requirement `{}` is not satisfied (`{}`)", - predicate, err) - } + ty::Predicate::Equate(ref predicate) => { + let predicate = self.resolve_type_vars_if_possible(predicate); + let err = self.equality_predicate(&obligation.cause, + &predicate).err().unwrap(); + struct_span_err!(self.tcx.sess, span, E0278, + "the requirement `{}` is not satisfied (`{}`)", + predicate, err) + } - ty::Predicate::RegionOutlives(ref predicate) => { - let predicate = self.resolve_type_vars_if_possible(predicate); - let err = self.region_outlives_predicate(&obligation.cause, - &predicate).err().unwrap(); - struct_span_err!(self.tcx.sess, span, E0279, - "the requirement `{}` is not satisfied (`{}`)", - predicate, err) - } + ty::Predicate::RegionOutlives(ref predicate) => { + let predicate = self.resolve_type_vars_if_possible(predicate); + let err = self.region_outlives_predicate(&obligation.cause, + &predicate).err().unwrap(); + struct_span_err!(self.tcx.sess, span, E0279, + "the requirement `{}` is not satisfied (`{}`)", + predicate, err) + } - ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { - let predicate = - self.resolve_type_vars_if_possible(&obligation.predicate); - struct_span_err!(self.tcx.sess, span, E0280, - "the requirement `{}` is not satisfied", - predicate) - } + ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { + let predicate = + self.resolve_type_vars_if_possible(&obligation.predicate); + struct_span_err!(self.tcx.sess, span, E0280, + "the requirement `{}` is not satisfied", + predicate) + } - ty::Predicate::ObjectSafe(trait_def_id) => { - let violations = self.tcx.object_safety_violations(trait_def_id); - self.tcx.report_object_safety_error(span, - trait_def_id, - violations) - } + ty::Predicate::ObjectSafe(trait_def_id) => { + let violations = self.tcx.object_safety_violations(trait_def_id); + self.tcx.report_object_safety_error(span, + trait_def_id, + violations) + } - ty::Predicate::ClosureKind(closure_def_id, kind) => { - let found_kind = self.closure_kind(closure_def_id).unwrap(); - let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap(); - let mut err = struct_span_err!( - self.tcx.sess, closure_span, E0525, - "expected a closure that implements the `{}` trait, \ - but this closure only implements `{}`", - kind, - found_kind); - err.span_note( - obligation.cause.span, - &format!("the requirement to implement \ - `{}` derives from here", kind)); - err.emit(); - return; - } + ty::Predicate::ClosureKind(closure_def_id, kind) => { + let found_kind = self.closure_kind(closure_def_id).unwrap(); + let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap(); + let mut err = struct_span_err!( + self.tcx.sess, closure_span, E0525, + "expected a closure that implements the `{}` trait, \ + but this closure only implements `{}`", + kind, + found_kind); + err.span_note( + obligation.cause.span, + &format!("the requirement to implement \ + `{}` derives from here", kind)); + err.emit(); + return; + } - ty::Predicate::WellFormed(ty) => { - // WF predicates cannot themselves make - // errors. They can only block due to - // ambiguity; otherwise, they always - // degenerate into other obligations - // (which may fail). - span_bug!(span, "WF predicate not satisfied for {:?}", ty); - } + ty::Predicate::WellFormed(ty) => { + // WF predicates cannot themselves make + // errors. They can only block due to + // ambiguity; otherwise, they always + // degenerate into other obligations + // (which may fail). + span_bug!(span, "WF predicate not satisfied for {:?}", ty); } } } From de2f7e15ba6db2846c80c7ad4ffe391f2c5a4311 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 19 Feb 2017 10:41:36 -0500 Subject: [PATCH 02/22] Rewrite `match` to use combinators. --- src/librustc/traits/error_reporting.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 411e986f62d90..a9f3c54bd73e0 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -535,14 +535,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return; } else { let trait_ref = trait_predicate.to_poly_trait_ref(); - let (post_message, pre_message) = match self.get_parent_trait_ref( - &obligation.cause.code) - { - Some(t) => { - (format!(" in `{}`", t), format!("within `{}`, ", t)) - } - None => (String::new(), String::new()), - }; + let (post_message, pre_message) = + self.get_parent_trait_ref(&obligation.cause.code) + .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t))) + .unwrap_or((String::new(), String::new())); let mut err = struct_span_err!( self.tcx.sess, span, From 83fe48d598ee188ae4d64a1fd12928e1026accf7 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 19 Feb 2017 10:46:43 -0500 Subject: [PATCH 03/22] Remove `else`, unindent. --- src/librustc/traits/error_reporting.rs | 91 +++++++++++++------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index a9f3c54bd73e0..193c07166b04e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -533,55 +533,54 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if self.tcx.sess.has_errors() && trait_predicate.references_error() { return; + } + let trait_ref = trait_predicate.to_poly_trait_ref(); + let (post_message, pre_message) = + self.get_parent_trait_ref(&obligation.cause.code) + .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t))) + .unwrap_or((String::new(), String::new())); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0277, + "the trait bound `{}` is not satisfied{}", + trait_ref.to_predicate(), + post_message); + err.span_label(span, + &format!("{}the trait `{}` is not \ + implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty())); + + // Try to report a help message + + if !trait_ref.has_infer_types() && + self.predicate_can_apply(trait_ref) { + // If a where-clause may be useful, remind the + // user that they can add it. + // + // don't display an on-unimplemented note, as + // these notes will often be of the form + // "the type `T` can't be frobnicated" + // which is somewhat confusing. + err.help(&format!("consider adding a `where {}` bound", + trait_ref.to_predicate())); + } else if let Some(s) = self.on_unimplemented_note(trait_ref, + obligation) { + // If it has a custom "#[rustc_on_unimplemented]" + // error message, let's display it! + err.note(&s); } else { - let trait_ref = trait_predicate.to_poly_trait_ref(); - let (post_message, pre_message) = - self.get_parent_trait_ref(&obligation.cause.code) - .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t))) - .unwrap_or((String::new(), String::new())); - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0277, - "the trait bound `{}` is not satisfied{}", - trait_ref.to_predicate(), - post_message); - err.span_label(span, - &format!("{}the trait `{}` is not \ - implemented for `{}`", - pre_message, - trait_ref, - trait_ref.self_ty())); - - // Try to report a help message - - if !trait_ref.has_infer_types() && - self.predicate_can_apply(trait_ref) { - // If a where-clause may be useful, remind the - // user that they can add it. - // - // don't display an on-unimplemented note, as - // these notes will often be of the form - // "the type `T` can't be frobnicated" - // which is somewhat confusing. - err.help(&format!("consider adding a `where {}` bound", - trait_ref.to_predicate())); - } else if let Some(s) = self.on_unimplemented_note(trait_ref, - obligation) { - // If it has a custom "#[rustc_on_unimplemented]" - // error message, let's display it! - err.note(&s); - } else { - // If we can't show anything useful, try to find - // similar impls. - let impl_candidates = - self.find_similar_impl_candidates(trait_ref); - if impl_candidates.len() > 0 { - self.report_similar_impl_candidates(trait_ref, &mut err); - } + // If we can't show anything useful, try to find + // similar impls. + let impl_candidates = + self.find_similar_impl_candidates(trait_ref); + if impl_candidates.len() > 0 { + self.report_similar_impl_candidates(trait_ref, &mut err); } - err } + err } ty::Predicate::Equate(ref predicate) => { From a97aed739b84df8d3bdd24e223dcd504e7e92615 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 19 Feb 2017 12:33:59 -0500 Subject: [PATCH 04/22] Remove unnecessary logic when finding simpilar `impl` candidates. --- src/librustc/traits/error_reporting.rs | 34 +++----------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 193c07166b04e..9354a8f735bc6 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -359,34 +359,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } fn report_similar_impl_candidates(&self, - trait_ref: ty::PolyTraitRef<'tcx>, + impl_candidates: Vec>, err: &mut DiagnosticBuilder) { - let simp = fast_reject::simplify_type(self.tcx, - trait_ref.skip_binder().self_ty(), - true); - let mut impl_candidates = Vec::new(); - let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id()); - - match simp { - Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| { - let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, - imp.self_ty(), - true); - if let Some(imp_simp) = imp_simp { - if simp != imp_simp { - return; - } - } - impl_candidates.push(imp); - }), - None => trait_def.for_each_impl(self.tcx, |def_id| { - impl_candidates.push( - self.tcx.impl_trait_ref(def_id).unwrap()); - }) - }; - if impl_candidates.is_empty() { return; } @@ -574,11 +549,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { // If we can't show anything useful, try to find // similar impls. - let impl_candidates = - self.find_similar_impl_candidates(trait_ref); - if impl_candidates.len() > 0 { - self.report_similar_impl_candidates(trait_ref, &mut err); - } + let impl_candidates = self.find_similar_impl_candidates(trait_ref); + self.report_similar_impl_candidates(impl_candidates, &mut err); } err } From 2436d7374caf1e25bfa8bacfb94c85d6d142332c Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 19 Feb 2017 13:00:25 -0500 Subject: [PATCH 05/22] Extract out error message generation. --- src/librustc/traits/error_reporting.rs | 34 +------------------------- src/librustc/traits/object_safety.rs | 20 +++++++++++++++ 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 9354a8f735bc6..11a777d5fe444 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -21,7 +21,6 @@ use super::{ SelectionContext, SelectionError, ObjectSafetyViolation, - MethodViolationCode, }; use fmt_macros::{Parser, Piece, Position}; @@ -679,38 +678,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if !reported_violations.insert(violation.clone()) { continue; } - let buf; - let note = match violation { - ObjectSafetyViolation::SizedSelf => { - "the trait cannot require that `Self : Sized`" - } - - ObjectSafetyViolation::SupertraitSelf => { - "the trait cannot use `Self` as a type parameter \ - in the supertrait listing" - } - - ObjectSafetyViolation::Method(name, - MethodViolationCode::StaticMethod) => { - buf = format!("method `{}` has no receiver", name); - &buf - } - - ObjectSafetyViolation::Method(name, - MethodViolationCode::ReferencesSelf) => { - buf = format!("method `{}` references the `Self` type \ - in its arguments or return type", - name); - &buf - } - - ObjectSafetyViolation::Method(name, - MethodViolationCode::Generic) => { - buf = format!("method `{}` has generic type parameters", name); - &buf - } - }; - err.note(note); + err.note(&violation.error_msg()); } err } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 60808fbc741fb..2ebe0d459fab1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -23,6 +23,7 @@ use hir::def_id::DefId; use traits; use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::subst::Substs; +use std::borrow::Cow; use syntax::ast; #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -38,6 +39,25 @@ pub enum ObjectSafetyViolation { Method(ast::Name, MethodViolationCode), } +impl ObjectSafetyViolation { + pub fn error_msg(&self) -> Cow<'static, str> { + match *self { + ObjectSafetyViolation::SizedSelf => + "the trait cannot require that `Self : Sized`".into(), + ObjectSafetyViolation::SupertraitSelf => + "the trait cannot use `Self` as a type parameter \ + in the supertrait listing".into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) => + format!("method `{}` has no receiver", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => + format!("method `{}` references the `Self` type \ + in its arguments or return type", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => + format!("method `{}` has generic type parameters", name).into(), + } + } +} + /// Reasons a method might not be object-safe. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum MethodViolationCode { From 10639d7958e951bb5478750e8fcce3eeda868304 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 19 Feb 2017 13:12:18 -0500 Subject: [PATCH 06/22] Add early return, remove `else`, unindent. --- src/librustc/traits/error_reporting.rs | 80 +++++++++++++------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 11a777d5fe444..c2fbccf82da94 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -708,46 +708,46 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let trait_ref = data.to_poly_trait_ref(); let self_ty = trait_ref.self_ty(); if predicate.references_error() { - } else { - // Typically, this ambiguity should only happen if - // there are unresolved type inference variables - // (otherwise it would suggest a coherence - // failure). But given #21974 that is not necessarily - // the case -- we can have multiple where clauses that - // are only distinguished by a region, which results - // in an ambiguity even when all types are fully - // known, since we don't dispatch based on region - // relationships. - - // This is kind of a hack: it frequently happens that some earlier - // error prevents types from being fully inferred, and then we get - // a bunch of uninteresting errors saying something like " doesn't implement Sized". It may even be true that we - // could just skip over all checks where the self-ty is an - // inference variable, but I was afraid that there might be an - // inference variable created, registered as an obligation, and - // then never forced by writeback, and hence by skipping here we'd - // be ignoring the fact that we don't KNOW the type works - // out. Though even that would probably be harmless, given that - // we're only talking about builtin traits, which are known to be - // inhabited. But in any case I just threw in this check for - // has_errors() to be sure that compilation isn't happening - // anyway. In that case, why inundate the user. - if !self.tcx.sess.has_errors() { - if - self.tcx.lang_items.sized_trait() - .map_or(false, |sized_id| sized_id == trait_ref.def_id()) - { - self.need_type_info(obligation, self_ty); - } else { - let mut err = struct_span_err!(self.tcx.sess, - obligation.cause.span, E0283, - "type annotations required: \ - cannot resolve `{}`", - predicate); - self.note_obligation_cause(&mut err, obligation); - err.emit(); - } + return; + } + // Typically, this ambiguity should only happen if + // there are unresolved type inference variables + // (otherwise it would suggest a coherence + // failure). But given #21974 that is not necessarily + // the case -- we can have multiple where clauses that + // are only distinguished by a region, which results + // in an ambiguity even when all types are fully + // known, since we don't dispatch based on region + // relationships. + + // This is kind of a hack: it frequently happens that some earlier + // error prevents types from being fully inferred, and then we get + // a bunch of uninteresting errors saying something like " doesn't implement Sized". It may even be true that we + // could just skip over all checks where the self-ty is an + // inference variable, but I was afraid that there might be an + // inference variable created, registered as an obligation, and + // then never forced by writeback, and hence by skipping here we'd + // be ignoring the fact that we don't KNOW the type works + // out. Though even that would probably be harmless, given that + // we're only talking about builtin traits, which are known to be + // inhabited. But in any case I just threw in this check for + // has_errors() to be sure that compilation isn't happening + // anyway. In that case, why inundate the user. + if !self.tcx.sess.has_errors() { + if + self.tcx.lang_items.sized_trait() + .map_or(false, |sized_id| sized_id == trait_ref.def_id()) + { + self.need_type_info(obligation, self_ty); + } else { + let mut err = struct_span_err!(self.tcx.sess, + obligation.cause.span, E0283, + "type annotations required: \ + cannot resolve `{}`", + predicate); + self.note_obligation_cause(&mut err, obligation); + err.emit(); } } } From 23d9211f1e2413243590757b68ec18b1fbc5d91f Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 19 Feb 2017 17:02:10 -0500 Subject: [PATCH 07/22] Flatten `for` loop using iterator combinators. --- src/librustc/traits/error_reporting.rs | 98 +++++++++++++------------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c2fbccf82da94..f850fd9772781 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -266,61 +266,63 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let span = obligation.cause.span; let mut report = None; - for item in self.tcx.get_attrs(def_id).iter() { - if item.check_name("rustc_on_unimplemented") { - let err_sp = item.meta().span.substitute_dummy(span); - let trait_str = self.tcx.item_path_str(trait_ref.def_id); - if let Some(istring) = item.value_str() { - let istring = &*istring.as_str(); - let generics = self.tcx.item_generics(trait_ref.def_id); - let generic_map = generics.types.iter().map(|param| { - (param.name.as_str().to_string(), - trait_ref.substs.type_for_def(param).to_string()) - }).collect::>(); - let parser = Parser::new(istring); - let mut errored = false; - let err: String = parser.filter_map(|p| { - match p { - Piece::String(s) => Some(s), - Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => match generic_map.get(s) { - Some(val) => Some(val), - None => { - span_err!(self.tcx.sess, err_sp, E0272, - "the #[rustc_on_unimplemented] \ - attribute on \ - trait definition for {} refers to \ - non-existent type parameter {}", - trait_str, s); - errored = true; - None - } - }, - _ => { - span_err!(self.tcx.sess, err_sp, E0273, - "the #[rustc_on_unimplemented] attribute \ - on trait definition for {} must have \ - named format arguments, eg \ - `#[rustc_on_unimplemented = \ - \"foo {{T}}\"]`", trait_str); + if let Some(item) = self.tcx + .get_attrs(def_id) + .into_iter() + .filter(|a| a.check_name("rustc_on_unimplemented")) + .next() + { + let err_sp = item.meta().span.substitute_dummy(span); + let trait_str = self.tcx.item_path_str(trait_ref.def_id); + if let Some(istring) = item.value_str() { + let istring = &*istring.as_str(); + let generics = self.tcx.item_generics(trait_ref.def_id); + let generic_map = generics.types.iter().map(|param| { + (param.name.as_str().to_string(), + trait_ref.substs.type_for_def(param).to_string()) + }).collect::>(); + let parser = Parser::new(istring); + let mut errored = false; + let err: String = parser.filter_map(|p| { + match p { + Piece::String(s) => Some(s), + Piece::NextArgument(a) => match a.position { + Position::ArgumentNamed(s) => match generic_map.get(s) { + Some(val) => Some(val), + None => { + span_err!(self.tcx.sess, err_sp, E0272, + "the #[rustc_on_unimplemented] \ + attribute on \ + trait definition for {} refers to \ + non-existent type parameter {}", + trait_str, s); errored = true; None } + }, + _ => { + span_err!(self.tcx.sess, err_sp, E0273, + "the #[rustc_on_unimplemented] attribute \ + on trait definition for {} must have \ + named format arguments, eg \ + `#[rustc_on_unimplemented = \ + \"foo {{T}}\"]`", trait_str); + errored = true; + None } } - }).collect(); - // Report only if the format string checks out - if !errored { - report = Some(err); } - } else { - span_err!(self.tcx.sess, err_sp, E0274, - "the #[rustc_on_unimplemented] attribute on \ - trait definition for {} must have a value, \ - eg `#[rustc_on_unimplemented = \"foo\"]`", - trait_str); + }).collect(); + // Report only if the format string checks out + if !errored { + report = Some(err); } - break; + } else { + span_err!(self.tcx.sess, err_sp, E0274, + "the #[rustc_on_unimplemented] attribute on \ + trait definition for {} must have a value, \ + eg `#[rustc_on_unimplemented = \"foo\"]`", + trait_str); } } report From a754ea6d0a6bc901e1c2dd58e3c0d0e283f8ae17 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 20 Feb 2017 09:23:40 -0500 Subject: [PATCH 08/22] Move `TraitRef` `impl` next to `struct` definition. --- src/librustc/ty/mod.rs | 18 ------------------ src/librustc/ty/sty.rs | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 7937d2ccfe46d..2a6ef13bfd2e2 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1086,24 +1086,6 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -impl<'tcx> TraitRef<'tcx> { - pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { - TraitRef { def_id: def_id, substs: substs } - } - - pub fn self_ty(&self) -> Ty<'tcx> { - self.substs.type_at(0) - } - - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { - // Select only the "input types" from a trait-reference. For - // now this is all the types that appear in the - // trait-reference, but it should eventually exclude - // associated types. - self.substs.types() - } -} - /// When type checking, we use the `ParameterEnvironment` to track /// details about the type/lifetime parameters that are in scope. /// It primarily stores the bounds information. diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 862bc15c05260..64e5ec6aeb24b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -389,6 +389,24 @@ pub struct TraitRef<'tcx> { pub substs: &'tcx Substs<'tcx>, } +impl<'tcx> TraitRef<'tcx> { + pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { + TraitRef { def_id: def_id, substs: substs } + } + + pub fn self_ty(&self) -> Ty<'tcx> { + self.substs.type_at(0) + } + + pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { + // Select only the "input types" from a trait-reference. For + // now this is all the types that appear in the + // trait-reference, but it should eventually exclude + // associated types. + self.substs.types() + } +} + pub type PolyTraitRef<'tcx> = Binder>; impl<'tcx> PolyTraitRef<'tcx> { From 5b504b7c030f88c10519d9a85ccf9897cec720a0 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Thu, 23 Feb 2017 21:15:30 +1030 Subject: [PATCH 09/22] Replace ./configure with config.toml in README.md and CONTRIBUTING.md --- CONTRIBUTING.md | 52 +++++++++++++++++++++++++++---------------------- README.md | 30 ++++++++++------------------ 2 files changed, 39 insertions(+), 43 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9d8c84f40715..8974242cea33a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,33 +97,36 @@ system internals, try asking in [`#rust-internals`][pound-rust-internals]. Before you can start building the compiler you need to configure the build for your system. In most cases, that will just mean using the defaults provided -for Rust. Configuring involves invoking the `configure` script in the project -root. +for Rust. -``` -./configure -``` +To change configuration, you must copy the file `src/bootstrap/config.toml.example` +to `config.toml` in the project root, and change the settings provided. + +There are large number of options provided in this config file that will alter the +configuration used in the build process. Some options to note: -There are large number of options accepted by this script to alter the -configuration used later in the build process. Some options to note: +#### `[llvm]`: +- `ccache = true` - Use ccache when building llvm -- `--enable-debug` - Build a debug version of the compiler (disables optimizations, - which speeds up compilation of stage1 rustc) -- `--enable-optimize` - Enable optimizations (can be used with `--enable-debug` - to make a debug build with optimizations) -- `--disable-valgrind-rpass` - Don't run tests with valgrind -- `--enable-clang` - Prefer clang to gcc for building dependencies (e.g., LLVM) -- `--enable-ccache` - Invoke clang/gcc with ccache to re-use object files between builds -- `--enable-compiler-docs` - Build compiler documentation +#### `[build]`: +- `compiler-docs = true` - Build compiler documentation -To see a full list of options, run `./configure --help`. +#### `[rust]`: +- `debuginfo = true` - Build a debug version of the compiler +- `optimize = false` - Disable optimizations to speed up compilation of stage1 rust + +For more options, the `config.toml` file contains commented out defaults, with +descriptions of what each option will do. + +Note: Previously the `./configure` script was used for configuration, but +is now deprecated. If you still have a `config.mk` file in your project root, +you may need to delete it for `config.toml` to work. ### Building -Although the `./configure` script will generate a `Makefile`, this is actually -just a thin veneer over the actual build system driver, `x.py`. This file, at -the root of the repository, is used to build, test, and document various parts -of the compiler. You can execute it as: +The build system uses the `x.py` script to control the build process. This script +is used to build, test, and document various parts of the compiler. You can +execute it as: ```sh python x.py build @@ -185,6 +188,9 @@ To learn about all possible rules you can execute, run: python x.py build --help --verbose ``` +Note: Previously `./configure` and `make` were used to build this project, +but these are now deprecated. + ### Useful commands Some common invocations of `x.py` are: @@ -235,8 +241,8 @@ feature. We use the 'fork and pull' model described there. Please make pull requests against the `master` branch. -Compiling all of `make check` can take a while. When testing your pull request, -consider using one of the more specialized `make` targets to cut down on the +Compiling all of `./x.py test` can take a while. When testing your pull request, +consider using one of the more specialized `./x.py` targets to cut down on the amount of time you have to wait. You need to have built the compiler at least once before running these will work, but that’s only one full build rather than one each time. @@ -307,7 +313,7 @@ To find documentation-related issues, sort by the [A-docs label][adocs]. [adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AA-docs -In many cases, you don't need a full `make doc`. You can use `rustdoc` directly +In many cases, you don't need a full `./x.py doc`. You can use `rustdoc` directly to check small fixes. For example, `rustdoc src/doc/reference.md` will render reference to `doc/reference.html`. The CSS might be messed up, but you can verify that the HTML is right. diff --git a/README.md b/README.md index c1218e9c600ce..5eef62cfb7d98 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ Read ["Installing Rust"] from [The Book]. * `g++` 4.7 or later or `clang++` 3.x * `python` 2.7 (but not 3.x) - * GNU `make` 3.81 or later * `cmake` 3.4.3 or later * `curl` * `git` @@ -35,15 +34,16 @@ Read ["Installing Rust"] from [The Book]. 3. Build and install: ```sh - $ ./configure + $ ./x.py build && sudo ./x.py dist $ make && sudo make install ``` - > ***Note:*** Install locations can be adjusted by passing a `--prefix` - > argument to `configure`. Various other options are also supported – pass - > `--help` for more information on them. + > ***Note:*** Install locations can be adjusted by copying the config file + > from `./src/bootstrap/config.toml.example` to `./config.toml`, and + > adjusting the `prefix` option under `[install]`. Various other options are + > also supported, and are documented in the config file. - When complete, `sudo make install` will place several programs into + When complete, `sudo ./x.py dist` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the API-documentation tool. This install does not include [Cargo], Rust's package manager, which you may also want to build. @@ -94,11 +94,10 @@ build. mingw-w64-x86_64-gcc ``` -4. Navigate to Rust's source code (or clone it), then configure and build it: +4. Navigate to Rust's source code (or clone it), then build it: ```sh - $ ./configure - $ make && make install + $ ./x.py build && ./x.py dist ``` #### MSVC @@ -107,20 +106,12 @@ MSVC builds of Rust additionally require an installation of Visual Studio 2013 (or later) so `rustc` can use its linker. Make sure to check the “C++ tools” option. -With these dependencies installed, you can build the compiler in a `cmd.exe` -shell with: +With these dependencies installed, you can build the compiler with: ```sh > python x.py build ``` -If you're running inside of an msys shell, however, you can run: - -```sh -$ ./configure --build=x86_64-pc-windows-msvc -$ make && make install -``` - Currently building Rust only works with some known versions of Visual Studio. If you have a more recent version installed the build system doesn't understand then you may need to force rustbuild to use an older version. This can be done @@ -136,8 +127,7 @@ python x.py build If you’d like to build the documentation, it’s almost the same: ```sh -$ ./configure -$ make docs +$ ./x.py doc ``` The generated documentation will appear in a top-level `doc` directory, From babcfb91bb4eea1e8372b92d5bf551bcc2a228b2 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Thu, 23 Feb 2017 23:06:37 +1030 Subject: [PATCH 10/22] Add back make depednency and msvc instructions --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 5eef62cfb7d98..a190cda1fb52c 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Read ["Installing Rust"] from [The Book]. * `g++` 4.7 or later or `clang++` 3.x * `python` 2.7 (but not 3.x) + * GNU `make` 3.81 or later * `cmake` 3.4.3 or later * `curl` * `git` @@ -112,6 +113,12 @@ With these dependencies installed, you can build the compiler with: > python x.py build ``` +If you're running inside of an msys shell, however, you can run: + +```sh +$ ./x.py build --build=x86_64-pc-windows-msvc && ./x.py dist +``` + Currently building Rust only works with some known versions of Visual Studio. If you have a more recent version installed the build system doesn't understand then you may need to force rustbuild to use an older version. This can be done From a00ab046b06d09dfbd709462795c4ae7afa67da8 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Thu, 23 Feb 2017 23:13:25 +1030 Subject: [PATCH 11/22] Invoke dist with --install --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a190cda1fb52c..8cd9eb5437561 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Read ["Installing Rust"] from [The Book]. 3. Build and install: ```sh - $ ./x.py build && sudo ./x.py dist + $ ./x.py build && sudo ./x.py dist --install $ make && sudo make install ``` @@ -44,7 +44,7 @@ Read ["Installing Rust"] from [The Book]. > adjusting the `prefix` option under `[install]`. Various other options are > also supported, and are documented in the config file. - When complete, `sudo ./x.py dist` will place several programs into + When complete, `sudo ./x.py dist --install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the API-documentation tool. This install does not include [Cargo], Rust's package manager, which you may also want to build. @@ -98,7 +98,7 @@ build. 4. Navigate to Rust's source code (or clone it), then build it: ```sh - $ ./x.py build && ./x.py dist + $ ./x.py build && ./x.py dist --install ``` #### MSVC @@ -116,7 +116,7 @@ With these dependencies installed, you can build the compiler with: If you're running inside of an msys shell, however, you can run: ```sh -$ ./x.py build --build=x86_64-pc-windows-msvc && ./x.py dist +$ ./x.py build --build=x86_64-pc-windows-msvc && ./x.py dist --install ``` Currently building Rust only works with some known versions of Visual Studio. If From 32a42482e869ad0cc15328bf2b08f21d8429d016 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Thu, 23 Feb 2017 23:15:36 +1030 Subject: [PATCH 12/22] Update wording of location to copy config.toml --- CONTRIBUTING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8974242cea33a..e806ad337015a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -100,7 +100,8 @@ your system. In most cases, that will just mean using the defaults provided for Rust. To change configuration, you must copy the file `src/bootstrap/config.toml.example` -to `config.toml` in the project root, and change the settings provided. +to `config.toml` in the directory from which you will be running the build, and +change the settings provided. There are large number of options provided in this config file that will alter the configuration used in the build process. Some options to note: @@ -119,7 +120,7 @@ For more options, the `config.toml` file contains commented out defaults, with descriptions of what each option will do. Note: Previously the `./configure` script was used for configuration, but -is now deprecated. If you still have a `config.mk` file in your project root, +is now deprecated. If you still have a `config.mk` file in your directory, you may need to delete it for `config.toml` to work. ### Building From 6c79a0e12516782e758385815fd025f8145eefd9 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Fri, 24 Feb 2017 08:59:46 +1030 Subject: [PATCH 13/22] Fix debuginfo reference --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e806ad337015a..e950e5c585dec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -113,7 +113,7 @@ configuration used in the build process. Some options to note: - `compiler-docs = true` - Build compiler documentation #### `[rust]`: -- `debuginfo = true` - Build a debug version of the compiler +- `debuginfo = true` - Build a compiler with debuginfo - `optimize = false` - Disable optimizations to speed up compilation of stage1 rust For more options, the `config.toml` file contains commented out defaults, with From e2e85b766d03c10030b052cedfcb319b41700d4f Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Fri, 24 Feb 2017 09:00:10 +1030 Subject: [PATCH 14/22] Update notes regarding ./configure and configuration --- CONTRIBUTING.md | 11 ++++++----- README.md | 24 ++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e950e5c585dec..1e983cfd726d6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -119,9 +119,10 @@ configuration used in the build process. Some options to note: For more options, the `config.toml` file contains commented out defaults, with descriptions of what each option will do. -Note: Previously the `./configure` script was used for configuration, but -is now deprecated. If you still have a `config.mk` file in your directory, -you may need to delete it for `config.toml` to work. +Note: Previously the `./configure` script was used to configure this +project. It can still be used, but it's recommended to use a `config.toml` +file. If you still have a `config.mk` file in your directory - from +`./configure` - you may need to delete it for `config.toml` to work. ### Building @@ -189,8 +190,8 @@ To learn about all possible rules you can execute, run: python x.py build --help --verbose ``` -Note: Previously `./configure` and `make` were used to build this project, -but these are now deprecated. +Note: Previously `./configure` and `make` were used to build this project. +They are still available, but `x.py` is the recommended build system. ### Useful commands diff --git a/README.md b/README.md index 8cd9eb5437561..4af7b9df7bd03 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,6 @@ Read ["Installing Rust"] from [The Book]. ```sh $ ./x.py build && sudo ./x.py dist --install - $ make && sudo make install ``` > ***Note:*** Install locations can be adjusted by copying the config file @@ -116,9 +115,16 @@ With these dependencies installed, you can build the compiler with: If you're running inside of an msys shell, however, you can run: ```sh -$ ./x.py build --build=x86_64-pc-windows-msvc && ./x.py dist --install +$ ./x.py build --build=x86_64-pc-windows-msvc +$ ./x.py dist --build=x86_64-pc-windows-msvc --install ``` + > ***Note:*** The build option can also be configured by copying + > the config file and adjusting the `build` option under `[build]`. + > ```sh + > $ cp ./src/bootstrap/config.toml.example ./config.toml + > ``` + Currently building Rust only works with some known versions of Visual Studio. If you have a more recent version installed the build system doesn't understand then you may need to force rustbuild to use an older version. This can be done @@ -129,6 +135,20 @@ CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64. python x.py build ``` +### Configure and Make + +While it's not the recommended build system, this project also provides a +configure script and makefile (the latter of which just invokes `x.py`). + +```sh +$ ./configure +$ make && sudo make install +``` + +When using the configure script, the generated config.mk` file may override the +`config.toml` file. To go back to the `config.toml` file, delete the generated +`config.mk` file. + ## Building Documentation If you’d like to build the documentation, it’s almost the same: From 8c8eda8ecd00f6fa145448dc81e746ab8c8113b7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Feb 2017 12:51:28 +0100 Subject: [PATCH 15/22] Fix nightly-only experimental API display --- src/librustdoc/html/render.rs | 8 ++++---- src/test/rustdoc/issue-27759.rs | 4 ++-- src/test/rustdoc/issue-32374.rs | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ae4c94d4b38c0..bb39c8c4f22ff 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1878,7 +1878,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec 0 => - format!(" ({} #{})", + format!(" ({} #{})", Escape(&stab.feature), tracker_url, issue_no, issue_no), (false, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 => format!(" (#{})", Escape(&tracker_url), issue_no, @@ -1890,12 +1890,12 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec\ 🔬 \ - This is a nightly-only experimental API.  {}\ + This is a nightly-only experimental API. {}\ ", - unstable_extra)); + unstable_extra)); } else { let text = format!("🔬 \ - This is a nightly-only experimental API.  {}\ + This is a nightly-only experimental API. {}\ {}", unstable_extra, MarkdownHtml(&stab.unstable_reason)); stability.push(format!("
{}
", diff --git a/src/test/rustdoc/issue-27759.rs b/src/test/rustdoc/issue-27759.rs index fe40ce2bd7ddb..e82e93230aa07 100644 --- a/src/test/rustdoc/issue-27759.rs +++ b/src/test/rustdoc/issue-27759.rs @@ -14,12 +14,12 @@ #![unstable(feature="test", issue="27759")] // @has issue_27759/unstable/index.html -// @has - 'test' +// @has - 'test ' // @has - '#27759' #[unstable(feature="test", issue="27759")] pub mod unstable { // @has issue_27759/unstable/fn.issue.html - // @has - 'test_function' + // @has - 'test_function ' // @has - '#1234567890' #[unstable(feature="test_function", issue="1234567890")] pub fn issue() {} diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 5cca370829201..6d1f8bc1cf9ba 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -18,10 +18,10 @@ // @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: text' -// @has - 'test' +// @has - 'test ' // @has - '#32374' // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \ -// '🔬 This is a nightly-only experimental API. \(test #32374\)$' +// '🔬 This is a nightly-only experimental API. \(test #32374\)$' #[rustc_deprecated(since = "1.0.0", reason = "text")] #[unstable(feature = "test", issue = "32374")] pub struct T; @@ -29,11 +29,11 @@ pub struct T; // @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: deprecated' // @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \ -// '🔬 This is a nightly-only experimental API. (test #32374)' +// '🔬 This is a nightly-only experimental API. (test #32374)' // @has issue_32374/struct.U.html '//details' \ -// '🔬 This is a nightly-only experimental API. (test #32374)' +// '🔬 This is a nightly-only experimental API. (test #32374)' // @has issue_32374/struct.U.html '//summary' \ -// '🔬 This is a nightly-only experimental API. (test #32374)' +// '🔬 This is a nightly-only experimental API. (test #32374)' // @has issue_32374/struct.U.html '//details/p' \ // 'unstable' #[rustc_deprecated(since = "1.0.0", reason = "deprecated")] From 78030391fb3f2b1ca853c85b8823c2e1e273ec9c Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 16 Feb 2017 20:54:24 -0800 Subject: [PATCH 16/22] travis: Fuchsia builder This change introduces a Dockerfile and script which builds a complete Fuchsia toolchain which can be used to build Rust distribution for Fuchsia. We only support cross-compiling at the moment, hence only setting the target. --- src/ci/docker/cross/Dockerfile | 28 ++++++- src/ci/docker/cross/build-fuchsia.sh | 114 +++++++++++++++++++++++++++ src/ci/docker/cross/shared.sh | 25 ++++++ src/tools/build-manifest/src/main.rs | 2 + 4 files changed, 165 insertions(+), 4 deletions(-) create mode 100755 src/ci/docker/cross/build-fuchsia.sh create mode 100644 src/ci/docker/cross/shared.sh diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index 52c5b83f26322..8d0f1d913b2ed 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -3,12 +3,12 @@ FROM ubuntu:16.04 RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ make \ + ninja-build \ file \ curl \ ca-certificates \ - python2.7 \ + python2.7-dev \ git \ - cmake \ sudo \ xz-utils \ zlib1g-dev \ @@ -19,7 +19,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ bzip2 \ patch \ libssl-dev \ - pkg-config + pkg-config \ + swig \ + libedit-dev \ + libncurses5-dev + +# CMake 3.8.0 is the first version with official support for Fuchsia, +# which is needed to build the Fuchsia toolchain. +RUN curl -L https://cmake.org/files/v3.8/cmake-3.8.0-rc1-Linux-x86_64.tar.gz | \ + tar xzf - -C /usr/local --strip-components=1 ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ @@ -31,6 +39,10 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini ENTRYPOINT ["/usr/bin/dumb-init", "--"] WORKDIR /tmp +COPY shared.sh /tmp/ + +COPY build-fuchsia.sh /tmp/ +RUN ./build-fuchsia.sh COPY build-rumprun.sh /tmp/ RUN ./build-rumprun.sh @@ -65,10 +77,18 @@ ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu +ENV TARGETS=$TARGETS,x86_64-unknown-fuchsia +ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ - CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc + CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ + AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \ + CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \ + CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \ + AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \ + CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \ + CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ # Suppress some warnings in the openwrt toolchains we downloaded ENV STAGING_DIR=/tmp diff --git a/src/ci/docker/cross/build-fuchsia.sh b/src/ci/docker/cross/build-fuchsia.sh new file mode 100755 index 0000000000000..73bd1d93101a5 --- /dev/null +++ b/src/ci/docker/cross/build-fuchsia.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# Copyright 2017 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +set -ex +source shared.sh + +# Download sources +SRCS=( + "https://fuchsia.googlesource.com/magenta magenta ac69119" + "https://fuchsia.googlesource.com/third_party/llvm llvm 5463083" + "https://fuchsia.googlesource.com/third_party/clang llvm/tools/clang 4ff7b4b" + "https://fuchsia.googlesource.com/third_party/lld llvm/tools/lld fd465a3" + "https://fuchsia.googlesource.com/third_party/lldb llvm/tools/lldb 6bb11f8" + "https://fuchsia.googlesource.com/third_party/compiler-rt llvm/runtimes/compiler-rt 52d4ecc" + "https://fuchsia.googlesource.com/third_party/libcxx llvm/runtimes/libcxx e891cc8" + "https://fuchsia.googlesource.com/third_party/libcxxabi llvm/runtimes/libcxxabi f0f0257" + "https://fuchsia.googlesource.com/third_party/libunwind llvm/runtimes/libunwind 50bddc1" +) + +fetch() { + mkdir -p $2 + pushd $2 > /dev/null + curl -sL $1/+archive/$3.tar.gz | tar xzf - + popd > /dev/null +} + +for i in "${SRCS[@]}"; do + fetch $i +done + +# Build toolchain +cd llvm +mkdir build +cd build +hide_output cmake -GNinja \ + -DFUCHSIA_SYSROOT=${PWD}/../../magenta/third_party/ulib/musl \ + -C ../tools/clang/cmake/caches/Fuchsia.cmake \ + .. +hide_output ninja stage2-distribution +hide_output ninja stage2-install-distribution +cd ../.. + +# Build sysroot +rm -rf llvm/runtimes/compiler-rt +./magenta/scripts/download-toolchain + +build_sysroot() { + local arch="$1" + + case "${arch}" in + x86_64) tgt="magenta-pc-x86-64" ;; + aarch64) tgt="magenta-qemu-arm64" ;; + esac + + hide_output make -C magenta -j$(getconf _NPROCESSORS_ONLN) $tgt + dst=/usr/local/${arch}-unknown-fuchsia + mkdir -p $dst + cp -r magenta/build-${tgt}/sysroot/include $dst/ + cp -r magenta/build-${tgt}/sysroot/lib $dst/ + + cd llvm + mkdir build-runtimes-${arch} + cd build-runtimes-${arch} + hide_output cmake -GNinja \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_AR=/usr/local/bin/llvm-ar \ + -DCMAKE_RANLIB=/usr/local/bin/llvm-ranlib \ + -DCMAKE_INSTALL_PREFIX= \ + -DLLVM_MAIN_SRC_DIR=${PWD}/.. \ + -DLLVM_BINARY_DIR=${PWD}/../build \ + -DLLVM_ENABLE_WERROR=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_INCLUDE_TESTS=ON \ + -DCMAKE_SYSTEM_NAME=Fuchsia \ + -DCMAKE_C_COMPILER_TARGET=${arch}-fuchsia \ + -DCMAKE_CXX_COMPILER_TARGET=${arch}-fuchsia \ + -DUNIX=1 \ + -DLIBCXX_HAS_MUSL_LIBC=ON \ + -DLIBCXXABI_USE_LLVM_UNWINDER=ON \ + -DCMAKE_SYSROOT=${dst} \ + -DCMAKE_C_COMPILER_FORCED=TRUE \ + -DCMAKE_CXX_COMPILER_FORCED=TRUE \ + -DLLVM_ENABLE_LIBCXX=ON \ + -DCMAKE_EXE_LINKER_FLAGS="-nodefaultlibs -lc" \ + -DCMAKE_SHARED_LINKER_FLAGS="$(clang --target=${arch}-fuchsia -print-libgcc-file-name)" \ + ../runtimes + hide_output env DESTDIR="${dst}" ninja install + cd ../.. +} + +build_sysroot "x86_64" +build_sysroot "aarch64" + +rm -rf magenta llvm + +for arch in x86_64 aarch64; do + for tool in clang clang++; do + cat >/usr/local/bin/${arch}-unknown-fuchsia-${tool} < or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + "$@" &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 991cd02d215dc..eba77429f3dbb 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -45,6 +45,7 @@ static HOSTS: &'static [&'static str] = &[ static TARGETS: &'static [&'static str] = &[ "aarch64-apple-ios", + "aarch64-unknown-fuchsia", "aarch64-linux-android", "aarch64-unknown-linux-gnu", "arm-linux-androideabi", @@ -86,6 +87,7 @@ static TARGETS: &'static [&'static str] = &[ "x86_64-pc-windows-msvc", "x86_64-rumprun-netbsd", "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", From bf878c8dc37afcd6703d5c1bd37e479399df47e9 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Sun, 26 Feb 2017 23:50:16 +1030 Subject: [PATCH 17/22] Mention windows ABIs explicitly in README.md --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4af7b9df7bd03..0929640760a5b 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,6 @@ for interop with software produced by Visual Studio use the MSVC build of Rust; for interop with GNU software built using the MinGW/MSYS2 toolchain use the GNU build. - #### MinGW [MSYS2][msys2] can be used to easily build Rust on Windows: @@ -106,25 +105,13 @@ MSVC builds of Rust additionally require an installation of Visual Studio 2013 (or later) so `rustc` can use its linker. Make sure to check the “C++ tools” option. -With these dependencies installed, you can build the compiler with: +With these dependencies installed, you can build the compiler in a `cmd.exe` +shell with: ```sh > python x.py build ``` -If you're running inside of an msys shell, however, you can run: - -```sh -$ ./x.py build --build=x86_64-pc-windows-msvc -$ ./x.py dist --build=x86_64-pc-windows-msvc --install -``` - - > ***Note:*** The build option can also be configured by copying - > the config file and adjusting the `build` option under `[build]`. - > ```sh - > $ cp ./src/bootstrap/config.toml.example ./config.toml - > ``` - Currently building Rust only works with some known versions of Visual Studio. If you have a more recent version installed the build system doesn't understand then you may need to force rustbuild to use an older version. This can be done @@ -135,6 +122,19 @@ CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64. python x.py build ``` +#### Specifying an ABI + +Each specific ABI can also be used from either environment (for example, using +the GNU ABI in powershell) by using an explicit build triple. The available +Windows build triples are: +- `x86_64-pc-windows-gnu` - The GNU ABI (using GCC) +- `x86_64-pc-windows-msvc` - The MSVC ABI + +The build triple can be specified by either specifying `--build=ABI` when +invoking `x.py` commands, or by copying the `config.toml` file (as described +in Building From Source), and modifying the `build` option under the `[build]` +section. + ### Configure and Make While it's not the recommended build system, this project also provides a From 2c695d761160f1448d7059e7b34102f198169a16 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Mon, 27 Feb 2017 00:03:08 +1030 Subject: [PATCH 18/22] List windows i686 ABIs --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0929640760a5b..93415adc423f4 100644 --- a/README.md +++ b/README.md @@ -127,8 +127,12 @@ python x.py build Each specific ABI can also be used from either environment (for example, using the GNU ABI in powershell) by using an explicit build triple. The available Windows build triples are: -- `x86_64-pc-windows-gnu` - The GNU ABI (using GCC) -- `x86_64-pc-windows-msvc` - The MSVC ABI +- GNU ABI (using GCC) + - `i686-pc-windows-gnu` + - `x86_64-pc-windows-gnu` +- The MSVC ABI + - `i686-pc-windows-msvc` + - `x86_64-pc-windows-msvc` The build triple can be specified by either specifying `--build=ABI` when invoking `x.py` commands, or by copying the `config.toml` file (as described From 8079bf35c596eef32ec872d35e28c90e4744f61e Mon Sep 17 00:00:00 2001 From: Robin Stocker Date: Mon, 27 Feb 2017 17:01:47 +1100 Subject: [PATCH 19/22] Example for how to provide stdin using std::process::Command Spawning a child process and writing to its stdin is a bit tricky due to `as_mut` and having to use a limited borrow. An example for this might help newer users. --- src/libstd/process.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 4ff35738b50fb..f846ef3e69e09 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -27,6 +27,31 @@ //! //! assert!(ecode.success()); //! ``` +//! +//! Calling a command with input and reading its output: +//! +//! ```no_run +//! use std::process::{Command, Stdio}; +//! use std::io::Write; +//! +//! let mut child = Command::new("/bin/cat") +//! .stdin(Stdio::piped()) +//! .stdout(Stdio::piped()) +//! .spawn() +//! .expect("failed to execute child"); +//! +//! { +//! // limited borrow of stdin +//! let stdin = child.stdin.as_mut().expect("failed to get stdin"); +//! stdin.write_all(b"test").expect("failed to write to stdin"); +//! } +//! +//! let output = child +//! .wait_with_output() +//! .expect("failed to wait on child"); +//! +//! assert_eq!(b"test", output.stdout.as_slice()); +//! ``` #![stable(feature = "process", since = "1.0.0")] From e998666a776dc73bd7c1c2ca7edde8ece48dfd36 Mon Sep 17 00:00:00 2001 From: Hiroki Kobayashi Date: Tue, 28 Feb 2017 00:47:24 +0900 Subject: [PATCH 20/22] Remove unnecessary "for" --- src/doc/book/src/procedural-macros.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md index 4f5a6a7c0332d..e02b5a6cdd79b 100644 --- a/src/doc/book/src/procedural-macros.md +++ b/src/doc/book/src/procedural-macros.md @@ -128,7 +128,7 @@ pub fn hello_world(input: TokenStream) -> TokenStream { So there is a lot going on here. We have introduced two new crates: [`syn`] and [`quote`]. As you may have noticed, `input: TokenSteam` is immediately converted to a `String`. This `String` is a string representation of the Rust code for which -we are deriving `HelloWorld` for. At the moment, the only thing you can do with a +we are deriving `HelloWorld`. At the moment, the only thing you can do with a `TokenStream` is convert it to a string. A richer API will exist in the future. So what we really need is to be able to _parse_ Rust code into something From b70f929396b09de5557e9432417488981b960eb6 Mon Sep 17 00:00:00 2001 From: Josef Brandl Date: Mon, 27 Feb 2017 21:49:05 +0100 Subject: [PATCH 21/22] Make lifetime elision docs clearer --- src/doc/book/src/lifetimes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/book/src/lifetimes.md b/src/doc/book/src/lifetimes.md index 8bca13c28f0bd..042d9af9717d0 100644 --- a/src/doc/book/src/lifetimes.md +++ b/src/doc/book/src/lifetimes.md @@ -349,8 +349,8 @@ to it. ## Lifetime Elision -Rust supports powerful local type inference in the bodies of functions but not in their item signatures. -It's forbidden to allow reasoning about types based on the item signature alone. +Rust supports powerful local type inference in the bodies of functions, but it +deliberately does not perform any reasoning about types for item signatures. However, for ergonomic reasons, a very restricted secondary inference algorithm called “lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision From 988be44c36f320e1aff08a0cf9a531441477b9d7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 23 Feb 2017 14:04:09 +0900 Subject: [PATCH 22/22] Add compile fail test for unboxed_closures feature --- .../feature-gate-unboxed-closures.rs | 24 +++++++++++++++++++ src/tools/tidy/src/features.rs | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/feature-gate-unboxed-closures.rs diff --git a/src/test/compile-fail/feature-gate-unboxed-closures.rs b/src/test/compile-fail/feature-gate-unboxed-closures.rs new file mode 100644 index 0000000000000..4005021774443 --- /dev/null +++ b/src/test/compile-fail/feature-gate-unboxed-closures.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Test; + +impl FnOnce<(u32, u32)> for Test { + type Output = u32; + + extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 { + a + b + } + //~^^^ ERROR rust-call ABI is subject to change (see issue #29625) +} + +fn main() { + assert_eq!(Test(1u32, 2u32), 3u32); +} diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 2c81382bc9b08..c84fefd872e47 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -169,8 +169,8 @@ pub fn check(path: &Path, bad: &mut bool) { let whitelist = vec![ "abi_ptx", "simd", "cfg_target_has_atomic", - "unboxed_closures", "stmt_expr_attributes", - "cfg_target_thread_local", "unwind_attributes" + "stmt_expr_attributes", + "cfg_target_thread_local", "unwind_attributes", ]; // Only check the number of lang features.