valopt i686-linux-android-ndk "" "i686-linux-android NDK standalone path"
valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path"
valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path"
+valopt nacl-cross-path "" "NaCl SDK path (Pepper Canary is recommended). Must be absolute!"
valopt release-channel "dev" "the name of the release channel to build"
valopt musl-root "/usr/local" "MUSL root installation directory"
fi
done
;;
-
+ *-unknown-nacl)
+ if [ -z "$CFG_NACL_CROSS_PATH" ]
+ then
+ err "I need the NaCl SDK path! (use --nacl-cross-path)"
+ fi
+ ;;
arm-apple-darwin)
if [ $CFG_OSTYPE != apple-darwin ]
then
putvar CFG_AARCH64_LINUX_ANDROID_NDK
putvar CFG_ARM_LINUX_ANDROIDEABI_NDK
putvar CFG_I686_LINUX_ANDROID_NDK
+putvar CFG_NACL_CROSS_PATH
putvar CFG_MANDIR
putvar CFG_USING_LIBCPP
--- /dev/null
+# le32-unknown-nacl (portable, PNaCl)
+ifneq ($(CFG_NACL_CROSS_PATH),)
+
+CC_le32-unknown-nacl=$(shell $(CFG_PYTHON) $(CFG_NACL_CROSS_PATH)/tools/nacl_config.py -t pnacl --tool cc)
+CXX_le32-unknown-nacl=$(shell $(CFG_PYTHON) $(CFG_NACL_CROSS_PATH)/tools/nacl_config.py -t pnacl --tool c++)
+CPP_le32-unknown-nacl=$(CXX_le32-unknown-nacl) -E
+AR_le32-unknown-nacl=$(shell $(CFG_PYTHON) $(CFG_NACL_CROSS_PATH)/tools/nacl_config.py -t pnacl --tool ar)
+
+CFG_PNACL_TOOLCHAIN := $(abspath $(dir $(AR_le32-unknown-nacl)/../))
+
+# Note: pso's aren't supported by PNaCl.
+CFG_LIB_NAME_le32-unknown-nacl=lib$(1).pso
+CFG_STATIC_LIB_NAME_le32-unknown-nacl=lib$(1).a
+CFG_LIB_GLOB_le32-unknown-nacl=lib$(1)-*.pso
+CFG_LIB_DSYM_GLOB_le32-unknown-nacl=lib$(1)-*.dylib.dSYM
+CFG_GCCISH_CFLAGS_le32-unknown-nacl := -Wall -Wno-unused-variable -Wno-unused-value $(shell $(CFG_PYTHON) $(CFG_NACL_CROSS_PATH)/tools/nacl_config.py -t pnacl --cflags) -D_YUGA_LITTLE_ENDIAN=1 -D_YUGA_BIG_ENDIAN=0
+CFG_GCCISH_CXXFLAGS_le32-unknown-nacl := -stdlib=libc++ $(CFG_GCCISH_CFLAGS_le32-unknown-nacl)
+CFG_GCCISH_LINK_FLAGS_le32-unknown-nacl := -static -pthread -lm
+CFG_GCCISH_DEF_FLAG_le32-unknown-nacl := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_le32-unknown-nacl := -Wl,-no-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_le32-unknown-nacl :=
+CFG_DEF_SUFFIX_le32-unknown-nacl := .le32.nacl.def
+CFG_INSTALL_NAME_le32-unknown-nacl =
+CFG_EXE_SUFFIX_le32-unknown-nacl = .pexe
+CFG_WINDOWSY_le32-unknown-nacl :=
+CFG_UNIXY_le32-unknown-nacl := 1
+CFG_NACLY_le32-unknown-nacl := 1
+CFG_PATH_MUNGE_le32-unknown-nacl := true
+CFG_LDPATH_le32-unknown-nacl :=
+CFG_RUN_le32-unknown-nacl=$(2)
+CFG_RUN_TARG_le32-unknown-nacl=$(call CFG_RUN_le32-unknown-nacl,,$(2))
+RUSTC_FLAGS_le32-unknown-nacl:=
+RUSTC_CROSS_FLAGS_le32-unknown-nacl=-L $(CFG_NACL_CROSS_PATH)/lib/pnacl/Release -L $(CFG_PNACL_TOOLCHAIN)/lib/clang/3.7.0/lib/le32-nacl -L $(CFG_PNACL_TOOLCHAIN)/le32-nacl/usr/lib -L $(CFG_PNACL_TOOLCHAIN)/le32-nacl/lib
+CFG_GNU_TRIPLE_le32-unknown-nacl := le32-unknown-nacl
+
+# strdup isn't defined unless -std=gnu++11 is used :/
+LLVM_FILTER_CXXFLAGS_le32-unknown-nacl := -std=c++11
+LLVM_EXTRA_CXXFLAGS_le32-unknown-nacl := -std=gnu++11
+
+endif
# LLVM macros
######################################################################
-LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc
+LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl
LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \
interpreter instrumentation
* - `deprecated` - Allows using the `#[deprecated]` attribute.
+* - `type_ascription` - Allows type ascription expressions `expr: Type`.
+
If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about `#![feature]` directives which enabled
the new feature (because the directive is no longer necessary). However, if a
use fmt;
use str::FromStr;
-use self::parse::{parse_decimal, Decimal, Sign};
-use self::parse::ParseResult::{Valid, Invalid, ShortcutToInf, ShortcutToZero};
+use self::parse::{parse_decimal, Decimal, Sign, ParseResult};
use self::num::digits_to_big;
use self::rawfp::RawFloat;
}
let (sign, s) = extract_sign(s);
let flt = match parse_decimal(s) {
- Valid(decimal) => try!(convert(decimal)),
- ShortcutToInf => T::infinity(),
- ShortcutToZero => T::zero(),
- Invalid => match s {
+ ParseResult::Valid(decimal) => try!(convert(decimal)),
+ ParseResult::ShortcutToInf => T::infinity(),
+ ParseResult::ShortcutToZero => T::zero(),
+ ParseResult::Invalid => match s {
"inf" => T::infinity(),
"NaN" => T::nan(),
_ => { return Err(pfe_invalid()); }
-Subproject commit 867c6ff0b824d6d295951ed34bb252d5e0b2467a
+Subproject commit 4b9b07c71997da23d5d1e3035cd16a5855b94ecc
macro_rules! mix {
() => {{
- a=a^(b<<11); d=d+a; b=b+c;
- b=b^(c>>2); e=e+b; c=c+d;
- c=c^(d<<8); f=f+c; d=d+e;
- d=d^(e>>16); g=g+d; e=e+f;
- e=e^(f<<10); h=h+e; f=f+g;
- f=f^(g>>4); a=a+f; g=g+h;
- g=g^(h<<8); b=b+g; h=h+a;
- h=h^(a>>9); c=c+h; a=a+b;
+ a = a ^ (b << 11);
+ d = d + a;
+ b = b + c;
+
+ b = b ^ (c >> 2);
+ e = e + b;
+ c = c + d;
+
+ c = c ^ (d << 8);
+ f = f + c;
+ d = d + e;
+
+ d = d ^ (e >> 16);
+ g = g + d;
+ e = e + f;
+
+ e = e ^ (f << 10);
+ h = h + e;
+ f = f + g;
+
+ f = f ^ (g >> 4);
+ a = a + f;
+ g = g + h;
+
+ g = g ^ (h << 8);
+ b = b + g;
+ h = h + a;
+
+ h = h ^ (a >> 9);
+ c = c + h;
+ a = a + b;
}}
}
macro_rules! mix {
() => {{
- a=a-e; f=f^(h>>9); h=h+a;
- b=b-f; g=g^(a<<9); a=a+b;
- c=c-g; h=h^(b>>23); b=b+c;
- d=d-h; a=a^(c<<15); c=c+d;
- e=e-a; b=b^(d>>14); d=d+e;
- f=f-b; c=c^(e<<20); e=e+f;
- g=g-c; d=d^(f>>17); f=f+g;
- h=h-d; e=e^(g<<14); g=g+h;
+ a = a - e;
+ f = f ^ (h >> 9);
+ h = h + a;
+
+ b = b - f;
+ g = g ^ (a << 9);
+ a = a + b;
+
+ c = c - g;
+ h = h ^ (b >> 23);
+ b = b + c;
+
+ d = d - h;
+ a = a ^ (c << 15);
+ c = c + d;
+
+ e = e - a;
+ b = b ^ (d >> 14);
+ d = d + e;
+
+ f = f - b;
+ c = c ^ (e << 20);
+ e = e + f;
+
+ g = g - c;
+ d = d ^ (f >> 17);
+ f = f + g;
+
+ h = h - d;
+ e = e ^ (g << 14);
+ g = g + h;
}}
}
hir::ExprBox(ref e) |
hir::ExprAddrOf(_, ref e) |
hir::ExprCast(ref e, _) |
+ hir::ExprType(ref e, _) |
hir::ExprUnary(_, ref e) |
hir::ExprField(ref e, _) |
hir::ExprTupField(ref e, _) => {
hir::ExprField(..) |
hir::ExprTupField(..) |
hir::ExprVec(_) |
+ hir::ExprType(..) |
hir::ExprTup(..) => {}
// Conditional control flow (possible to implement).
None => unreachable!(),
}
}
+ hir::ExprType(ref e, _) => try!(eval_const_expr_partial(tcx, &**e, ty_hint, fn_args)),
hir::ExprTup(_) => Tuple(e.id),
hir::ExprStruct(..) => Struct(e.id),
hir::ExprIndex(ref arr, ref idx) => {
match expr.node {
hir::ExprPath(..) => { }
+ hir::ExprType(ref subexpr, _) => {
+ self.walk_expr(&**subexpr)
+ }
+
hir::ExprUnary(hir::UnDeref, ref base) => { // *base
if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
self.select_from_expr(&**base);
// where the error was detected. But that span is not readily
// accessible.
- let is_warning = match origin {
- infer::RFC1214Subregion(_) => true,
- _ => false,
- };
-
let labeled_user_string = match bound_kind {
GenericKind::Param(ref p) =>
format!("the parameter type `{}`", p),
match sub {
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
- span_err_or_warn!(
- is_warning, self.tcx.sess, origin.span(), E0309,
+ span_err!(
+ self.tcx.sess, origin.span(), E0309,
"{} may not live long enough", labeled_user_string);
self.tcx.sess.fileline_help(
origin.span(),
ty::ReStatic => {
// Does the required lifetime have a nice name we can print?
- span_err_or_warn!(
- is_warning, self.tcx.sess, origin.span(), E0310,
+ span_err!(
+ self.tcx.sess, origin.span(), E0310,
"{} may not live long enough", labeled_user_string);
self.tcx.sess.fileline_help(
origin.span(),
_ => {
// If not, be less specific.
- span_err_or_warn!(
- is_warning, self.tcx.sess, origin.span(), E0311,
+ span_err!(
+ self.tcx.sess, origin.span(), E0311,
"{} may not live long enough",
labeled_user_string);
self.tcx.sess.fileline_help(
}
}
- if is_warning {
- self.tcx.sess.note_rfc_1214(origin.span());
- }
-
self.note_region_origin(&origin);
}
sub: Region,
sup: Region) {
match origin {
- infer::RFC1214Subregion(ref suborigin) => {
- // Ideally, this would be a warning, but it doesn't
- // seem to come up in practice, since the changes from
- // RFC1214 mostly trigger errors in type definitions
- // that don't wind up coming down this path.
- self.report_concrete_failure((**suborigin).clone(), sub, sup);
- }
infer::Subtype(trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
self.report_and_explain_type_error(trace, &terr);
fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
match *origin {
- infer::RFC1214Subregion(ref suborigin) => {
- self.note_region_origin(suborigin);
- }
infer::Subtype(ref trace) => {
let desc = match trace.origin {
TypeOrigin::Misc(_) => {
use rustc_data_structures::unify::{self, UnificationTable};
use std::cell::{RefCell, Ref};
use std::fmt;
-use std::rc::Rc;
use syntax::ast;
use syntax::codemap;
use syntax::codemap::{Span, DUMMY_SP};
/// See `error_reporting.rs` for more details
#[derive(Clone, Debug)]
pub enum SubregionOrigin<'tcx> {
- // Marker to indicate a constraint that only arises due to new
- // provisions from RFC 1214. This will result in a warning, not an
- // error.
- RFC1214Subregion(Rc<SubregionOrigin<'tcx>>),
-
// Arose from a subtyping relation
Subtype(TypeTrace<'tcx>),
impl<'tcx> SubregionOrigin<'tcx> {
pub fn span(&self) -> Span {
match *self {
- RFC1214Subregion(ref a) => a.span(),
Subtype(ref a) => a.span(),
InfStackClosure(a) => a,
InvokeClosure(a) => a,
hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprInlineAsm(..) | hir::ExprBox(..) |
- hir::ExprRange(..) => {
+ hir::ExprRange(..) | hir::ExprType(..) => {
intravisit::walk_expr(ir, expr);
}
}
hir::ExprBox(ref e) |
hir::ExprAddrOf(_, ref e) |
hir::ExprCast(ref e, _) |
+ hir::ExprType(ref e, _) |
hir::ExprUnary(_, ref e) => {
self.propagate_through_expr(&**e, succ)
}
hir::ExprBlock(..) | hir::ExprAddrOf(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) |
- hir::ExprRange(..) => {
+ hir::ExprRange(..) | hir::ExprType(..) => {
intravisit::walk_expr(this, expr);
}
}
self.cat_def(expr.id, expr.span, expr_ty, def)
}
+ hir::ExprType(ref e, _) => {
+ self.cat_expr(&**e)
+ }
+
hir::ExprAddrOf(..) | hir::ExprCall(..) |
hir::ExprAssign(..) | hir::ExprAssignOp(..) |
hir::ExprClosure(..) | hir::ExprRet(..) |
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TraitErrorKey<'tcx> {
- is_warning: bool,
span: Span,
predicate: ty::Predicate<'tcx>
}
let predicate =
infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
TraitErrorKey {
- is_warning: is_warning(&e.obligation),
span: e.obligation.cause.span,
predicate: infcx.tcx.erase_regions(&predicate)
}
}
}
-fn is_warning<T>(obligation: &Obligation<T>) -> bool {
- obligation.cause.code.is_rfc1214()
-}
-
pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
obligation: &PredicateObligation<'tcx>,
error: &MismatchedProjectionTypes<'tcx>)
// then $X will be unified with TyError, but the error still needs to be
// reported.
if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
- span_err_or_warn!(
- is_warning(obligation), infcx.tcx.sess, obligation.cause.span, E0271,
+ span_err!(
+ infcx.tcx.sess, obligation.cause.span, E0271,
"type mismatch resolving `{}`: {}",
predicate,
error.err);
obligation: &PredicateObligation<'tcx>,
error: &SelectionError<'tcx>)
{
- let is_warning = is_warning(obligation);
match *error {
SelectionError::Unimplemented => {
if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
- span_err_or_warn!(
- is_warning, infcx.tcx.sess, obligation.cause.span, E0276,
+ span_err!(
+ infcx.tcx.sess, obligation.cause.span, E0276,
"the requirement `{}` appears on the impl \
method but not on the corresponding trait method",
obligation.predicate);
if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
let trait_ref = trait_predicate.to_poly_trait_ref();
- span_err_or_warn!(
- is_warning, infcx.tcx.sess, obligation.cause.span, E0277,
+ span_err!(
+ infcx.tcx.sess, obligation.cause.span, E0277,
"the trait `{}` is not implemented for the type `{}`",
trait_ref, trait_ref.self_ty());
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.equality_predicate(obligation.cause.span,
&predicate).err().unwrap();
- span_err_or_warn!(
- is_warning, infcx.tcx.sess, obligation.cause.span, E0278,
+ span_err!(
+ infcx.tcx.sess, obligation.cause.span, E0278,
"the requirement `{}` is not satisfied (`{}`)",
predicate,
err);
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.region_outlives_predicate(obligation.cause.span,
&predicate).err().unwrap();
- span_err_or_warn!(
- is_warning, infcx.tcx.sess, obligation.cause.span, E0279,
+ span_err!(
+ infcx.tcx.sess, obligation.cause.span, E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate,
err);
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
- span_err_or_warn!(
- is_warning, infcx.tcx.sess, obligation.cause.span, E0280,
+ span_err!(
+ infcx.tcx.sess, obligation.cause.span, E0280,
"the requirement `{}` is not satisfied",
predicate);
note_obligation_cause(infcx, obligation);
report_object_safety_error(infcx.tcx,
obligation.cause.span,
trait_def_id,
- violations,
- is_warning);
+ violations);
note_obligation_cause(infcx, obligation);
}
let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
if !actual_trait_ref.self_ty().references_error() {
- span_err_or_warn!(
- is_warning, infcx.tcx.sess, obligation.cause.span, E0281,
+ span_err!(
+ infcx.tcx.sess, obligation.cause.span, E0281,
"type mismatch: the type `{}` implements the trait `{}`, \
but the trait `{}` is required ({})",
expected_trait_ref.self_ty(),
TraitNotObjectSafe(did) => {
let violations = object_safety_violations(infcx.tcx, did);
- report_object_safety_error(infcx.tcx, obligation.cause.span, did,
- violations, is_warning);
+ report_object_safety_error(infcx.tcx, obligation.cause.span, did, violations);
note_obligation_cause(infcx, obligation);
}
}
pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
trait_def_id: DefId,
- violations: Vec<ObjectSafetyViolation>,
- is_warning: bool)
+ violations: Vec<ObjectSafetyViolation>)
{
- span_err_or_warn!(
- is_warning, tcx.sess, span, E0038,
+ span_err!(
+ tcx.sess, span, E0038,
"the trait `{}` cannot be made into an object",
tcx.item_path_str(trait_def_id));
let self_ty = trait_ref.self_ty();
let all_types = &trait_ref.substs().types;
if all_types.references_error() {
- } else if all_types.needs_infer() {
+ } 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 "<generic
note_obligation_cause(infcx, obligation);
}
}
- } else if !infcx.tcx.sess.has_errors() {
- // Ambiguity. Coherence should have reported an error.
- infcx.tcx.sess.span_bug(
- obligation.cause.span,
- &format!(
- "coherence failed to report ambiguity: \
- cannot locate the impl of the trait `{}` for \
- the type `{}`",
- trait_ref,
- self_ty));
}
}
let tcx = infcx.tcx;
match *cause_code {
ObligationCauseCode::MiscObligation => { }
- ObligationCauseCode::RFC1214(ref subcode) => {
- tcx.sess.note_rfc_1214(cause_span);
- note_obligation_cause_code(infcx, predicate, cause_span, subcode);
- }
ObligationCauseCode::SliceOrArrayElem => {
tcx.sess.fileline_note(
cause_span,
use super::is_object_safe;
use super::FulfillmentError;
use super::ObligationCause;
-use super::ObligationCauseCode;
use super::PredicateObligation;
use super::project;
-use super::RFC1214Warning;
use super::select::SelectionContext;
use super::Unimplemented;
use super::util::predicate_for_builtin_bound;
pub struct FulfilledPredicates<'tcx> {
- set: FnvHashSet<(RFC1214Warning, ty::Predicate<'tcx>)>
+ set: FnvHashSet<ty::Predicate<'tcx>>
}
/// The fulfillment context is used to drive trait resolution. It
assert!(!obligation.has_escaping_regions());
- let w = RFC1214Warning(obligation.cause.code.is_rfc1214());
-
- if self.is_duplicate_or_add(infcx.tcx, w, &obligation.predicate) {
+ if self.is_duplicate_or_add(infcx.tcx, &obligation.predicate) {
debug!("register_predicate({:?}) -- already seen, skip", obligation);
return;
}
fn is_duplicate_or_add(&mut self,
tcx: &ty::ctxt<'tcx>,
- w: RFC1214Warning,
predicate: &ty::Predicate<'tcx>)
-> bool {
// This is a kind of dirty hack to allow us to avoid "rederiving"
// evaluating the 'nested obligations'. This cache lets us
// skip those.
- let will_warn_due_to_rfc1214 = w.0;
- let errors_will_be_reported = self.errors_will_be_reported && !will_warn_due_to_rfc1214;
- if errors_will_be_reported && predicate.is_global() {
- tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(w, predicate)
+ if self.errors_will_be_reported && predicate.is_global() {
+ tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(predicate)
} else {
- self.duplicate_set.is_duplicate_or_add(w, predicate)
+ self.duplicate_set.is_duplicate_or_add(predicate)
}
}
}
ty::Predicate::WellFormed(ty) => {
- let rfc1214 = match obligation.cause.code {
- ObligationCauseCode::RFC1214(_) => true,
- _ => false,
- };
match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
- ty, obligation.cause.span, rfc1214) {
+ ty, obligation.cause.span) {
Some(obligations) => {
new_obligations.extend(obligations);
true
}
}
- pub fn is_duplicate(&self, w: RFC1214Warning, p: &ty::Predicate<'tcx>) -> bool {
- let key = (w, p.clone());
- self.set.contains(&key)
+ pub fn is_duplicate(&self, key: &ty::Predicate<'tcx>) -> bool {
+ self.set.contains(key)
}
- fn is_duplicate_or_add(&mut self, w: RFC1214Warning, p: &ty::Predicate<'tcx>) -> bool {
- let key = (w, p.clone());
- !self.set.insert(key)
+ fn is_duplicate_or_add(&mut self, key: &ty::Predicate<'tcx>) -> bool {
+ !self.set.insert(key.clone())
}
}
/// Not well classified or should be obvious from span.
MiscObligation,
- /// Obligation that triggers warning until RFC 1214 is fully in place.
- RFC1214(Rc<ObligationCauseCode<'tcx>>),
-
/// This is the trait reference from the given projection
SliceOrArrayElem,
}
}
-/// This marker is used in some caches to record whether the
-/// predicate, if it is found to be false, will yield a warning (due
-/// to RFC1214) or an error. We separate these two cases in the cache
-/// so that if we see the same predicate twice, first resulting in a
-/// warning, and next resulting in an error, we still report the
-/// error, rather than considering it a duplicate.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct RFC1214Warning(bool);
-
-impl<'tcx> ObligationCauseCode<'tcx> {
- pub fn is_rfc1214(&self) -> bool {
- match *self {
- ObligationCauseCode::RFC1214(..) => true,
- _ => false,
- }
- }
-}
-
impl<'tcx, N> Vtable<'tcx, N> {
pub fn nested_obligations(self) -> Vec<N> {
match self {
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
use super::{ObjectCastObligation, Obligation};
use super::TraitNotObjectSafe;
-use super::RFC1214Warning;
use super::Selection;
use super::SelectionResult;
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
// have been proven elsewhere. This cache only contains
// predicates that are global in scope and hence unaffected by
// the current environment.
- let w = RFC1214Warning(false);
- if self.tcx().fulfilled_predicates.borrow().is_duplicate(w, &obligation.predicate) {
+ if self.tcx().fulfilled_predicates.borrow().is_duplicate(&obligation.predicate) {
return EvaluatedToOk;
}
ty::Predicate::WellFormed(ty) => {
match ty::wf::obligations(self.infcx, obligation.cause.body_id,
- ty, obligation.cause.span,
- obligation.cause.code.is_rfc1214()) {
+ ty, obligation.cause.span) {
Some(obligations) =>
self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
None =>
// chain. Ideally, we should have a way to configure this either
// by using -Z verbose or just a CLI argument.
if obligation.recursion_depth >= 0 {
- let derived_code = match obligation.cause.code {
- ObligationCauseCode::RFC1214(ref base_code) => {
- let derived_cause = DerivedObligationCause {
- parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
- parent_code: base_code.clone(),
- };
- ObligationCauseCode::RFC1214(Rc::new(variant(derived_cause)))
- }
- _ => {
- let derived_cause = DerivedObligationCause {
- parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
- parent_code: Rc::new(obligation.cause.code.clone())
- };
- variant(derived_cause)
- }
+ let derived_cause = DerivedObligationCause {
+ parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
+ parent_code: Rc::new(obligation.cause.code.clone())
};
+ let derived_code = variant(derived_cause);
ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
} else {
obligation.cause.clone()
}
}
+ hir::ExprType(ref e, _) => {
+ self.expr_is_lval(e)
+ }
+
hir::ExprUnary(hir::UnDeref, _) |
hir::ExprField(..) |
hir::ExprTupField(..) |
// them. This gives us room to improve the regionck reasoning in
// the future without breaking backwards compat.
EscapingProjection(Vec<Component<'tcx>>),
-
- // This is a temporary marker indicating "outlives components"
- // that are due to the new rules introduced by RFC 1214. For the
- // time being, violations of these requirements generally induce
- // warnings, not errors.
- RFC1214(Vec<Component<'tcx>>),
}
/// Returns all the things that must outlive `'a` for the condition
}
}
- // Bare functions and traits are both binders. In the RFC,
- // this means we would add the bound regions to the "bound
- // regions list". In our representation, no such list is
- // maintained explicitly, because bound regions themselves can
- // be readily identified. However, because the outlives
- // relation did not used to be applied to fn/trait-object
- // arguments, we wrap the resulting components in an RFC1214
- // wrapper so we can issue warnings.
- ty::TyBareFn(..) | ty::TyTrait(..) => {
- // OutlivesFunction, OutlivesObject, OutlivesFragment
- let subcomponents = capture_components(infcx, ty);
- out.push(Component::RFC1214(subcomponents));
- }
-
// OutlivesTypeParameterEnv -- the actual checking that `X:'a`
// is implied by the environment is done in regionck.
ty::TyParam(p) => {
ty::TyRawPtr(..) | // ...
ty::TyRef(..) | // OutlivesReference
ty::TyTuple(..) | // ...
+ ty::TyBareFn(..) | // OutlivesFunction (*)
+ ty::TyTrait(..) | // OutlivesObject, OutlivesFragment (*)
ty::TyError => {
+ // (*) Bare functions and traits are both binders. In the
+ // RFC, this means we would add the bound regions to the
+ // "bound regions list". In our representation, no such
+ // list is maintained explicitly, because bound regions
+ // themselves can be readily identified.
+
push_region_constraints(out, ty.regions());
for subty in ty.walk_shallow() {
compute_components(infcx, subty, out);
use middle::traits;
use middle::ty::{self, RegionEscape, ToPredicate, Ty};
use std::iter::once;
-use std::mem;
-use std::rc::Rc;
use syntax::ast;
use syntax::codemap::Span;
use util::common::ErrorReported;
pub fn obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
body_id: ast::NodeId,
ty: Ty<'tcx>,
- span: Span,
- rfc1214: bool)
+ span: Span)
-> Option<Vec<traits::PredicateObligation<'tcx>>>
{
let mut wf = WfPredicates { infcx: infcx,
body_id: body_id,
span: span,
- out: vec![],
- rfc1214: rfc1214 };
+ out: vec![] };
if wf.compute(ty) {
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
let result = wf.normalize();
pub fn trait_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
body_id: ast::NodeId,
trait_ref: &ty::TraitRef<'tcx>,
- span: Span,
- rfc1214: bool)
+ span: Span)
-> Vec<traits::PredicateObligation<'tcx>>
{
- let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span,
- out: vec![], rfc1214: rfc1214 };
+ let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span, out: vec![] };
wf.compute_trait_ref(trait_ref);
wf.normalize()
}
pub fn predicate_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
body_id: ast::NodeId,
predicate: &ty::Predicate<'tcx>,
- span: Span,
- rfc1214: bool)
+ span: Span)
-> Vec<traits::PredicateObligation<'tcx>>
{
- let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span,
- out: vec![], rfc1214: rfc1214 };
+ let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span, out: vec![] };
// (*) ok to skip binders, because wf code is prepared for it
match *predicate {
// than the ultimate set. (Note: normally there won't be
// unresolved inference variables here anyway, but there might be
// during typeck under some circumstances.)
- let obligations = obligations(infcx, body_id, ty, span, false).unwrap_or(vec![]);
+ let obligations = obligations(infcx, body_id, ty, span).unwrap_or(vec![]);
// From the full set of obligations, just filter down to the
// region relationships.
vec!(),
Component::UnresolvedInferenceVariable(..) =>
vec!(),
- Component::RFC1214(components) =>
- implied_bounds_from_components(sub_region, components),
}
})
.collect()
body_id: ast::NodeId,
span: Span,
out: Vec<traits::PredicateObligation<'tcx>>,
- rfc1214: bool
}
impl<'a,'tcx> WfPredicates<'a,'tcx> {
- fn rfc1214<R,F:FnOnce(&mut WfPredicates<'a,'tcx>) -> R>(&mut self, f: F) -> R {
- let b = mem::replace(&mut self.rfc1214, true);
- let r = f(self);
- self.rfc1214 = b;
- r
- }
-
fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
- if !self.rfc1214 {
- traits::ObligationCause::new(self.span, self.body_id, code)
- } else {
- let code = traits::ObligationCauseCode::RFC1214(Rc::new(code));
- traits::ObligationCause::new(self.span, self.body_id, code)
- }
+ traits::ObligationCause::new(self.span, self.body_id, code)
}
fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
.collect()
}
- fn compute_rfc1214(&mut self, ty: Ty<'tcx>) {
- let b = mem::replace(&mut self.rfc1214, true);
- for subty in ty.walk().skip(1) {
- self.compute(subty);
- }
- self.rfc1214 = b;
- }
-
/// Pushes the obligations required for `trait_ref` to be WF into
/// `self.out`.
fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
ty::TySlice(subty) |
ty::TyArray(subty, _) => {
- self.rfc1214(|this| {
- if !subty.has_escaping_regions() {
- let cause = this.cause(traits::SliceOrArrayElem);
- match traits::trait_ref_for_builtin_bound(this.infcx.tcx,
- ty::BoundSized,
- subty) {
- Ok(trait_ref) => {
- this.out.push(
- traits::Obligation::new(cause,
- trait_ref.to_predicate()));
- }
- Err(ErrorReported) => { }
+ if !subty.has_escaping_regions() {
+ let cause = self.cause(traits::SliceOrArrayElem);
+ match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
+ ty::BoundSized,
+ subty) {
+ Ok(trait_ref) => {
+ self.out.push(
+ traits::Obligation::new(cause,
+ trait_ref.to_predicate()));
}
+ Err(ErrorReported) => { }
}
- })
+ }
}
ty::TyBox(_) |
ty::TyClosure(..) => {
// the types in a closure are always the types of
// local variables (or possibly references to local
- // variables), which are separately checked w/r/t
- // WFedness.
+ // variables), we'll walk those.
+ //
+ // (Though, local variables are probably not
+ // needed, as they are separately checked w/r/t
+ // WFedness.)
}
ty::TyBareFn(..) => {
- // process the bound types; because the old implicator
- // did not do this, go into RFC1214 mode.
- subtys.skip_current_subtree();
- self.compute_rfc1214(ty);
+ // let the loop iterator into the argument/return
+ // types appearing in the fn signature
}
ty::TyTrait(ref data) => {
traits::Obligation::new(
cause,
ty::Predicate::ObjectSafe(data.principal_def_id())));
-
- // process the bound types; because the old implicator
- // did not do this, go into RFC1214 mode.
- subtys.skip_current_subtree();
- self.compute_rfc1214(ty);
}
// Inference variables are the complicated case, since we don't
None => self.diagnostic().span_err(sp, msg)
}
}
- pub fn note_rfc_1214(&self, span: Span) {
- self.span_note(
- span,
- &format!("this warning results from recent bug fixes and clarifications; \
- it will become a HARD ERROR in the next release. \
- See RFC 1214 for details."));
- }
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
match split_msg_into_multilines(msg) {
Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code),
pub out_filename: PathBuf,
pub is_like_osx: bool,
pub has_rpath: bool,
+ pub linker_is_gnu: bool,
pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf,
}
let libs = libs.into_iter().filter_map(|(_, l)| l).collect::<Vec<_>>();
let rpaths = get_rpaths(config, &libs[..]);
flags.extend_from_slice(&rpaths_to_flags(&rpaths[..]));
+
+ // Use DT_RUNPATH instead of DT_RPATH if available
+ if config.linker_is_gnu {
+ flags.push("-Wl,--enable-new-dtags".to_string());
+ }
+
flags
}
used_crates: Vec::new(),
has_rpath: true,
is_like_osx: true,
+ linker_is_gnu: false,
out_filename: PathBuf::from("bin/rustc"),
get_install_prefix_lib_path: &mut || panic!(),
};
get_install_prefix_lib_path: &mut || panic!(),
has_rpath: true,
is_like_osx: false,
+ linker_is_gnu: true,
};
let res = get_rpath_relative_to_output(config,
Path::new("lib/libstd.so"));
SawExprUnary(hir::UnOp),
SawExprLit(ast::Lit_),
SawExprCast,
+ SawExprType,
SawExprIf,
SawExprWhile,
SawExprMatch,
ExprUnary(op, _) => SawExprUnary(op),
ExprLit(ref lit) => SawExprLit(lit.node.clone()),
ExprCast(..) => SawExprCast,
+ ExprType(..) => SawExprType,
ExprIf(..) => SawExprIf,
ExprWhile(..) => SawExprWhile,
ExprLoop(_, id) => SawExprLoop(id.map(|id| id.name.as_str())),
ExprCast(expr, ty) => {
ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
}
+ ExprType(expr, ty) => {
+ ExprType(folder.fold_expr(expr), folder.fold_ty(ty))
+ }
ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
ExprIf(cond, tr, fl) => {
ExprIf(folder.fold_expr(cond),
ExprLit(P<Lit>),
/// A cast (`foo as f64`)
ExprCast(P<Expr>, P<Ty>),
+ ExprType(P<Expr>, P<Ty>),
/// An `if` block, with an optional else block
///
/// `if expr { block } else { expr }`
visitor.visit_expr(subexpression)
}
ExprLit(_) => {}
- ExprCast(ref subexpression, ref typ) => {
+ ExprCast(ref subexpression, ref typ) | ExprType(ref subexpression, ref typ) => {
visitor.visit_expr(subexpression);
visitor.visit_ty(typ)
}
let expr = lower_expr(lctx, expr);
hir::ExprCast(expr, lower_ty(lctx, ty))
}
+ ExprType(ref expr, ref ty) => {
+ let expr = lower_expr(lctx, expr);
+ hir::ExprType(expr, lower_ty(lctx, ty))
+ }
ExprAddrOf(m, ref ohs) => {
let m = lower_mutability(lctx, m);
let ohs = lower_expr(lctx, ohs);
hir::ExprBinary(..) |
hir::ExprClosure(..) |
hir::ExprAssignOp(..) |
- hir::ExprCast(..) => true,
+ hir::ExprCast(..) |
+ hir::ExprType(..) => true,
_ => false,
}
}
try!(self.word_space("as"));
try!(self.print_type(&**ty));
}
+ hir::ExprType(ref expr, ref ty) => {
+ try!(self.print_expr(&**expr));
+ try!(self.word_space(":"));
+ try!(self.print_type(&**ty));
+ }
hir::ExprIf(ref test, ref blk, ref elseopt) => {
try!(self.print_if(&**test, &**blk, elseopt.as_ref().map(|e| &**e)));
}
}
ast::ExprUnary(_, ref x) |
ast::ExprCast(ref x, _) |
+ ast::ExprType(ref x, _) |
ast::ExprField(ref x, _) |
ast::ExprTupField(ref x, _) |
ast::ExprIndex(ref x, _) => {
pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
- pub fn LLVMInitializeX86TargetInfo();
- pub fn LLVMInitializeX86Target();
- pub fn LLVMInitializeX86TargetMC();
- pub fn LLVMInitializeX86AsmPrinter();
- pub fn LLVMInitializeX86AsmParser();
- pub fn LLVMInitializeARMTargetInfo();
- pub fn LLVMInitializeARMTarget();
- pub fn LLVMInitializeARMTargetMC();
- pub fn LLVMInitializeARMAsmPrinter();
- pub fn LLVMInitializeARMAsmParser();
- pub fn LLVMInitializeAArch64TargetInfo();
- pub fn LLVMInitializeAArch64Target();
- pub fn LLVMInitializeAArch64TargetMC();
- pub fn LLVMInitializeAArch64AsmPrinter();
- pub fn LLVMInitializeAArch64AsmParser();
- pub fn LLVMInitializeMipsTargetInfo();
- pub fn LLVMInitializeMipsTarget();
- pub fn LLVMInitializeMipsTargetMC();
- pub fn LLVMInitializeMipsAsmPrinter();
- pub fn LLVMInitializeMipsAsmParser();
- pub fn LLVMInitializePowerPCTargetInfo();
- pub fn LLVMInitializePowerPCTarget();
- pub fn LLVMInitializePowerPCTargetMC();
- pub fn LLVMInitializePowerPCAsmPrinter();
- pub fn LLVMInitializePowerPCAsmParser();
-
pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: *const c_char) -> bool;
pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
CPU: *const c_char,
pub fn LLVMRustGetModuleDataLayout(M: ModuleRef) -> TargetDataRef;
}
+#[cfg(have_component_x86)]
+extern {
+ pub fn LLVMInitializeX86TargetInfo();
+ pub fn LLVMInitializeX86Target();
+ pub fn LLVMInitializeX86TargetMC();
+ pub fn LLVMInitializeX86AsmPrinter();
+ pub fn LLVMInitializeX86AsmParser();
+}
+#[cfg(have_component_arm)]
+extern {
+ pub fn LLVMInitializeARMTargetInfo();
+ pub fn LLVMInitializeARMTarget();
+ pub fn LLVMInitializeARMTargetMC();
+ pub fn LLVMInitializeARMAsmPrinter();
+ pub fn LLVMInitializeARMAsmParser();
+}
+#[cfg(have_component_aarch64)]
+extern {
+ pub fn LLVMInitializeAArch64TargetInfo();
+ pub fn LLVMInitializeAArch64Target();
+ pub fn LLVMInitializeAArch64TargetMC();
+ pub fn LLVMInitializeAArch64AsmPrinter();
+ pub fn LLVMInitializeAArch64AsmParser();
+}
+#[cfg(have_component_mips)]
+extern {
+ pub fn LLVMInitializeMipsTargetInfo();
+ pub fn LLVMInitializeMipsTarget();
+ pub fn LLVMInitializeMipsTargetMC();
+ pub fn LLVMInitializeMipsAsmPrinter();
+ pub fn LLVMInitializeMipsAsmParser();
+}
+#[cfg(have_component_powerpc)]
+extern {
+ pub fn LLVMInitializePowerPCTargetInfo();
+ pub fn LLVMInitializePowerPCTarget();
+ pub fn LLVMInitializePowerPCTargetMC();
+ pub fn LLVMInitializePowerPCAsmPrinter();
+ pub fn LLVMInitializePowerPCAsmParser();
+}
+#[cfg(have_component_pnacl)]
+extern {
+ pub fn LLVMInitializePNaClTargetInfo();
+ pub fn LLVMInitializePNaClTarget();
+ pub fn LLVMInitializePNaClTargetMC();
+}
+
// LLVM requires symbols from this library, but apparently they're not printed
// during llvm-config?
#[cfg(windows)]
init_target!(have_component_aarch64 AArch64);
init_target!(have_component_arm ARM);
init_target!(have_component_x86 X86);
+
+ // PNaCl doesn't provide some of the optional target components, so we
+ // manually initialize it here.
+ #[cfg(have_component_pnacl)]
+ fn init_pnacl() {
+ unsafe {
+ LLVMInitializePNaClTargetInfo();
+ LLVMInitializePNaClTarget();
+ LLVMInitializePNaClTargetMC();
+ }
+ }
+ #[cfg(not(have_component_pnacl))]
+ fn init_pnacl() { }
+ init_pnacl();
}
// The module containing the native LLVM dependencies, generated by the build system
name: Field::new(index.node as usize) },
hir::ExprCast(ref source, _) =>
ExprKind::Cast { source: source.to_ref() },
+ hir::ExprType(ref source, _) =>
+ return source.make_mirror(cx),
hir::ExprBox(ref value) =>
ExprKind::Box { value: value.to_ref() },
hir::ExprVec(ref fields) =>
out_filename: out_filename.to_path_buf(),
has_rpath: sess.target.target.options.has_rpath,
is_like_osx: sess.target.target.options.is_like_osx,
+ linker_is_gnu: sess.target.target.options.linker_is_gnu,
get_install_prefix_lib_path: &mut get_install_prefix_lib_path,
};
cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
try!(const_fn_call(cx, MethodCallKey(method_call),
method_did, &arg_vals, param_substs, trueconst))
},
+ hir::ExprType(ref e, _) => try!(const_expr(cx, &**e, param_substs, fn_args, trueconst)).0,
hir::ExprBlock(ref block) => {
match block.expr {
Some(ref expr) => try!(const_expr(
hir::ExprPath(..) => {}
hir::ExprCast(ref sub_exp, _) |
+ hir::ExprType(ref sub_exp, _) |
hir::ExprAddrOf(_, ref sub_exp) |
hir::ExprField(ref sub_exp, _) |
hir::ExprTupField(ref sub_exp, _) =>
let _icx = push_ctxt("trans_datum_unadjusted");
match expr.node {
+ hir::ExprType(ref e, _) => {
+ trans(bcx, &**e)
+ }
hir::ExprPath(..) => {
trans_def(bcx, expr, bcx.def(expr.id))
}
hir::ExprBreak(label_opt) => {
controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node.name))
}
+ hir::ExprType(ref e, _) => {
+ trans_into(bcx, &**e, Ignore)
+ }
hir::ExprAgain(label_opt) => {
controlflow::trans_cont(bcx, expr, label_opt.map(|l| l.node.name))
}
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
match expr.node {
+ hir::ExprType(ref e, _) => {
+ trans_into(bcx, &**e, dest)
+ }
hir::ExprPath(..) => {
trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
}
}
}
+ hir::ExprType(ref expr, _) => {
+ expr_kind(tcx, expr)
+ }
+
hir::ExprUnary(hir::UnDeref, _) |
hir::ExprField(..) |
hir::ExprTupField(..) |
// except according to those terms.
use llvm::BasicBlockRef;
+use middle::infer;
+use middle::ty;
use rustc::mir::repr as mir;
use trans::adt;
use trans::base;
use trans::build;
-use trans::common::Block;
+use trans::common::{self, Block};
use trans::debuginfo::DebugLoc;
+use trans::type_of;
use super::MirContext;
+use super::operand::OperandValue::{FatPtr, Immediate, Ref};
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
pub fn trans_block(&mut self, bb: mir::BasicBlock) {
base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
}
- mir::Terminator::Call { .. } => {
- unimplemented!()
- //let llbb = unimplemented!(); // self.make_landing_pad(panic_bb);
- //
- //let tr_dest = self.trans_lvalue(bcx, &data.destination);
- //
- //// Create the callee. This will always be a fn
- //// ptr and hence a kind of scalar.
- //let callee = self.trans_operand(bcx, &data.func);
- //
- //// Process the arguments.
- //
- //let args = unimplemented!();
- //
- //callee::trans_call_inner(bcx,
- // DebugLoc::None,
- // |bcx, _| Callee {
- // bcx: bcx,
- // data: CalleeData::Fn(callee.llval),
- // ty: callee.ty,
- // },
- // args,
- // Some(Dest::SaveIn(tr_dest.llval)));
+ mir::Terminator::Call { ref data, targets } => {
+ // The location we'll write the result of the call into.
+ let call_dest = self.trans_lvalue(bcx, &data.destination);
+
+ // Create the callee. This will always be a fn
+ // ptr and hence a kind of scalar.
+ let callee = self.trans_operand(bcx, &data.func);
+ let ret_ty = if let ty::TyBareFn(_, ref f) = callee.ty.sty {
+ let sig = bcx.tcx().erase_late_bound_regions(&f.sig);
+ let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
+ sig.output
+ } else {
+ panic!("trans_block: expected TyBareFn as callee");
+ };
+
+ // The arguments we'll be passing
+ let mut llargs = vec![];
+
+ // Does the fn use an outptr? If so, that's the first arg.
+ if let ty::FnConverging(ret_ty) = ret_ty {
+ if type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
+ llargs.push(call_dest.llval);
+ }
+ }
+
+ // Process the rest of the args.
+ for arg in &data.args {
+ let arg_op = self.trans_operand(bcx, arg);
+ match arg_op.val {
+ Ref(llval) | Immediate(llval) => llargs.push(llval),
+ FatPtr(base, extra) => {
+ // The two words in a fat ptr are passed separately
+ llargs.push(base);
+ llargs.push(extra);
+ }
+ }
+ }
+
+ // FIXME: Handle panics
+ //let panic_bb = self.llblock(targets.1);
+ //self.make_landing_pad(panic_bb);
+
+ // Do the actual call.
+ let (llret, b) = base::invoke(bcx,
+ callee.immediate(),
+ &llargs[..],
+ callee.ty,
+ DebugLoc::None);
+ bcx = b;
+
+ // Copy the return value into the destination.
+ if let ty::FnConverging(ret_ty) = ret_ty {
+ if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
+ !common::type_is_zero_size(bcx.ccx(), ret_ty) {
+ base::store_ty(bcx, llret, call_dest.llval, ret_ty);
+ }
+ }
+
+ build::Br(bcx, self.llblock(targets.0), DebugLoc::None)
}
}
}
traits::astconv_object_safety_violations(tcx, principal.def_id());
if !object_safety_violations.is_empty() {
traits::report_object_safety_error(
- tcx, span, principal.def_id(), object_safety_violations, false);
+ tcx, span, principal.def_id(), object_safety_violations);
return tcx.types.err;
}
pub mod demand;
pub mod method;
mod upvar;
-mod wf;
mod wfcheck;
mod cast;
mod closure;
}
}
-pub fn check_wf_old(ccx: &CrateCtxt) {
- // 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_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) {
ccx.tcx.sess.abort_if_new_errors(|| {
let krate = ccx.tcx.map.krate();
}
}
+fn check_expr_eq_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ expr: &'tcx hir::Expr,
+ expected: Ty<'tcx>) {
+ check_expr_with_unifier(
+ fcx, expr, ExpectHasType(expected), NoPreference,
+ || demand::eqtype(fcx, expr.span, expected, fcx.expr_ty(expr)));
+}
+
pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
expr: &'tcx hir::Expr,
expected: Ty<'tcx>) {
deferred_cast_checks.push(cast_check);
}
}
+ hir::ExprType(ref e, ref t) => {
+ let typ = fcx.to_ty(&**t);
+ check_expr_eq_type(fcx, &**e, typ);
+ fcx.write_ty(id, typ);
+ }
hir::ExprVec(ref args) => {
let uty = expected.to_option(fcx).and_then(|uty| {
match uty.sty {
use middle::ty::wf::ImpliedBound;
use std::mem;
-use std::rc::Rc;
use syntax::ast;
use syntax::codemap::Span;
use rustc_front::intravisit::{self, Visitor};
code: &traits::ObligationCauseCode<'tcx>)
-> SubregionOrigin<'tcx> {
match *code {
- traits::ObligationCauseCode::RFC1214(ref code) =>
- infer::RFC1214Subregion(Rc::new(self.code_to_origin(span, sup_type, code))),
traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) =>
infer::ReferenceOutlivesReferent(ref_type, span),
_ =>
origin.span(),
&format!("unresolved inference variable in outlives: {:?}", v));
}
- ty::outlives::Component::RFC1214(subcomponents) => {
- let suborigin = infer::RFC1214Subregion(Rc::new(origin));
- components_must_outlive(rcx, suborigin, subcomponents, region);
- }
}
}
}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use astconv::AstConv;
-use check::{FnCtxt, Inherited, blank_fn_ctxt, regionck, wfcheck};
-use constrained_type_params::{identify_constrained_type_params, Parameter};
-use CrateCtxt;
-use middle::region;
-use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
-use middle::traits;
-use middle::ty::{self, Ty};
-use middle::ty::fold::{TypeFolder, TypeFoldable, super_fold_ty};
-
-use std::cell::RefCell;
-use std::collections::HashSet;
-use syntax::ast;
-use syntax::codemap::{DUMMY_SP, Span};
-use syntax::parse::token::special_idents;
-
-use rustc_front::intravisit::{self, Visitor, FnKind};
-use rustc_front::hir;
-
-pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> {
- ccx: &'ccx CrateCtxt<'ccx, 'tcx>,
- cache: HashSet<Ty<'tcx>>
-}
-
-impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
- pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'tcx>) -> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
- CheckTypeWellFormedVisitor { ccx: ccx, cache: HashSet::new() }
- }
-
- fn tcx(&self) -> &ty::ctxt<'tcx> {
- self.ccx.tcx
- }
-
- /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
- /// well-formed, meaning that they do not require any constraints not declared in the struct
- /// definition itself. For example, this definition would be illegal:
- ///
- /// struct Ref<'a, T> { x: &'a T }
- ///
- /// because the type did not declare that `T:'a`.
- ///
- /// We do this check as a pre-pass before checking fn bodies because if these constraints are
- /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
- /// the types first.
- fn check_item_well_formed(&mut self, item: &hir::Item) {
- let ccx = self.ccx;
- debug!("check_item_well_formed(it.id={}, it.name={})",
- item.id,
- ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(item.id)));
-
- match item.node {
- /// Right now we check that every default trait implementation
- /// has an implementation of itself. Basically, a case like:
- ///
- /// `impl Trait for T {}`
- ///
- /// has a requirement of `T: Trait` which was required for default
- /// method implementations. Although this could be improved now that
- /// there's a better infrastructure in place for this, it's being left
- /// for a follow-up work.
- ///
- /// Since there's such a requirement, we need to check *just* positive
- /// implementations, otherwise things like:
- ///
- /// impl !Send for T {}
- ///
- /// won't be allowed unless there's an *explicit* implementation of `Send`
- /// for `T`
- hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _, _, _) => {
- self.check_impl(item);
- }
- hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), _, _) => {
- let item_def_id = ccx.tcx.map.local_def_id(item.id);
- let trait_ref = ccx.tcx.impl_trait_ref(item_def_id).unwrap();
- ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
- match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
- Some(ty::BoundSend) | Some(ty::BoundSync) => {}
- Some(_) | None => {
- if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
- wfcheck::error_192(ccx, item.span);
- }
- }
- }
- }
- hir::ItemFn(..) => {
- self.check_item_type(item);
- }
- hir::ItemStatic(..) => {
- self.check_item_type(item);
- }
- hir::ItemConst(..) => {
- self.check_item_type(item);
- }
- hir::ItemStruct(ref struct_def, ref ast_generics) => {
- self.check_type_defn(item, |fcx| {
- vec![struct_variant(fcx, struct_def)]
- });
-
- self.check_variances_for_type_defn(item, ast_generics);
- }
- hir::ItemEnum(ref enum_def, ref ast_generics) => {
- self.check_type_defn(item, |fcx| {
- enum_variants(fcx, enum_def)
- });
-
- self.check_variances_for_type_defn(item, ast_generics);
- }
- hir::ItemTrait(_, _, _, ref items) => {
- let trait_predicates =
- ccx.tcx.lookup_predicates(ccx.tcx.map.local_def_id(item.id));
- reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
- if ccx.tcx.trait_has_default_impl(ccx.tcx.map.local_def_id(item.id)) {
- if !items.is_empty() {
- wfcheck::error_380(ccx, item.span);
- }
- }
- }
- _ => {}
- }
- }
-
- fn with_fcx<F>(&mut self, item: &hir::Item, mut f: F) where
- F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, &FnCtxt<'fcx, 'tcx>),
- {
- let ccx = self.ccx;
- let item_def_id = ccx.tcx.map.local_def_id(item.id);
- let type_scheme = ccx.tcx.lookup_item_type(item_def_id);
- let type_predicates = ccx.tcx.lookup_predicates(item_def_id);
- reject_non_type_param_bounds(ccx.tcx, item.span, &type_predicates);
- let free_id_outlive = ccx.tcx.region_maps.item_extent(item.id);
- let param_env = ccx.tcx.construct_parameter_environment(item.span,
- &type_scheme.generics,
- &type_predicates,
- free_id_outlive);
- let tables = RefCell::new(ty::Tables::empty());
- let inh = Inherited::new(ccx.tcx, &tables, param_env);
- let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id);
- f(self, &fcx);
- fcx.select_all_obligations_or_error();
- regionck::regionck_item(&fcx, item.id, item.span, &[]);
- }
-
- /// In a type definition, we check that to ensure that the types of the fields are well-formed.
- fn check_type_defn<F>(&mut self, item: &hir::Item, mut lookup_fields: F) where
- F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
- {
- self.with_fcx(item, |this, fcx| {
- let variants = lookup_fields(fcx);
- let mut bounds_checker = BoundsChecker::new(fcx,
- item.id,
- Some(&mut this.cache));
- debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope);
-
- for variant in &variants {
- for field in &variant.fields {
- // Regions are checked below.
- bounds_checker.check_traits_in_ty(field.ty, field.span);
- }
-
- // For DST, all intermediate types must be sized.
- if let Some((_, fields)) = variant.fields.split_last() {
- for field in fields {
- fcx.register_builtin_bound(
- field.ty,
- ty::BoundSized,
- traits::ObligationCause::new(field.span,
- fcx.body_id,
- traits::FieldSized));
- }
- }
- }
-
- for field in variants.iter().flat_map(|v| v.fields.iter()) {
- fcx.register_old_wf_obligation(field.ty, field.span, traits::MiscObligation);
- }
- });
- }
-
- fn check_item_type(&mut self,
- item: &hir::Item)
- {
- self.with_fcx(item, |this, fcx| {
- let mut bounds_checker = BoundsChecker::new(fcx,
- item.id,
- Some(&mut this.cache));
- debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope);
-
- let item_def_id = fcx.tcx().map.local_def_id(item.id);
- let type_scheme = fcx.tcx().lookup_item_type(item_def_id);
- let item_ty = fcx.instantiate_type_scheme(item.span,
- &fcx.inh
- .infcx
- .parameter_environment
- .free_substs,
- &type_scheme.ty);
-
- bounds_checker.check_traits_in_ty(item_ty, item.span);
- });
- }
-
- fn check_impl(&mut self,
- item: &hir::Item)
- {
- self.with_fcx(item, |this, fcx| {
- let mut bounds_checker = BoundsChecker::new(fcx,
- item.id,
- Some(&mut this.cache));
- debug!("check_impl at bounds_checker.scope: {:?}", bounds_checker.scope);
-
- // Find the impl self type as seen from the "inside" --
- // that is, with all type parameters converted from bound
- // to free.
- let self_ty = fcx.tcx().node_id_to_type(item.id);
- let self_ty = fcx.instantiate_type_scheme(item.span,
- &fcx.inh
- .infcx
- .parameter_environment
- .free_substs,
- &self_ty);
-
- bounds_checker.check_traits_in_ty(self_ty, item.span);
-
- // Similarly, obtain an "inside" reference to the trait
- // that the impl implements.
- let trait_ref = match fcx.tcx().impl_trait_ref(fcx.tcx().map.local_def_id(item.id)) {
- None => { return; }
- Some(t) => { t }
- };
-
- let trait_ref = fcx.instantiate_type_scheme(item.span,
- &fcx.inh
- .infcx
- .parameter_environment
- .free_substs,
- &trait_ref);
-
- // We are stricter on the trait-ref in an impl than the
- // self-type. In particular, we enforce region
- // relationships. The reason for this is that (at least
- // presently) "applying" an impl does not require that the
- // application site check the well-formedness constraints on the
- // trait reference. Instead, this is done at the impl site.
- // Arguably this is wrong and we should treat the trait-reference
- // the same way as we treat the self-type.
- bounds_checker.check_trait_ref(&trait_ref, item.span);
-
- let cause =
- traits::ObligationCause::new(
- item.span,
- fcx.body_id,
- traits::ItemObligation(trait_ref.def_id));
-
- // Find the supertrait bounds. This will add `int:Bar`.
- let poly_trait_ref = ty::Binder(trait_ref);
- let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id());
- let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref);
- let predicates = {
- let selcx = &mut traits::SelectionContext::new(fcx.infcx());
- traits::normalize(selcx, cause.clone(), &predicates)
- };
- for predicate in predicates.value.predicates {
- fcx.register_predicate(traits::Obligation::new(cause.clone(), predicate));
- }
- for obligation in predicates.obligations {
- fcx.register_predicate(obligation);
- }
- });
- }
-
- fn check_variances_for_type_defn(&self,
- item: &hir::Item,
- ast_generics: &hir::Generics)
- {
- let item_def_id = self.tcx().map.local_def_id(item.id);
- let ty_predicates = self.tcx().lookup_predicates(item_def_id);
- let variances = self.tcx().item_variances(item_def_id);
-
- let mut constrained_parameters: HashSet<_> =
- variances.types
- .iter_enumerated()
- .filter(|&(_, _, &variance)| variance != ty::Bivariant)
- .map(|(space, index, _)| self.param_ty(ast_generics, space, index))
- .map(|p| Parameter::Type(p))
- .collect();
-
- identify_constrained_type_params(self.tcx(),
- ty_predicates.predicates.as_slice(),
- None,
- &mut constrained_parameters);
-
- for (space, index, _) in variances.types.iter_enumerated() {
- let param_ty = self.param_ty(ast_generics, space, index);
- if constrained_parameters.contains(&Parameter::Type(param_ty)) {
- continue;
- }
- let span = self.ty_param_span(ast_generics, item, space, index);
- self.report_bivariance(span, param_ty.name);
- }
-
- for (space, index, &variance) in variances.regions.iter_enumerated() {
- if variance != ty::Bivariant {
- continue;
- }
-
- assert_eq!(space, TypeSpace);
- let span = ast_generics.lifetimes[index].lifetime.span;
- let name = ast_generics.lifetimes[index].lifetime.name;
- self.report_bivariance(span, name);
- }
- }
-
- fn param_ty(&self,
- ast_generics: &hir::Generics,
- space: ParamSpace,
- index: usize)
- -> ty::ParamTy
- {
- let name = match space {
- TypeSpace => ast_generics.ty_params[index].name,
- SelfSpace => special_idents::type_self.name,
- FnSpace => self.tcx().sess.bug("Fn space occupied?"),
- };
-
- ty::ParamTy { space: space, idx: index as u32, name: name }
- }
-
- fn ty_param_span(&self,
- ast_generics: &hir::Generics,
- item: &hir::Item,
- space: ParamSpace,
- index: usize)
- -> Span
- {
- match space {
- TypeSpace => ast_generics.ty_params[index].span,
- SelfSpace => item.span,
- FnSpace => self.tcx().sess.span_bug(item.span, "Fn space occupied?"),
- }
- }
-
- fn report_bivariance(&self,
- span: Span,
- param_name: ast::Name)
- {
- wfcheck::error_392(self.tcx(), span, param_name);
-
- let suggested_marker_id = self.tcx().lang_items.phantom_data();
- match suggested_marker_id {
- Some(def_id) => {
- self.tcx().sess.fileline_help(
- span,
- &format!("consider removing `{}` or using a marker such as `{}`",
- param_name,
- self.tcx().item_path_str(def_id)));
- }
- None => {
- // no lang items, no help!
- }
- }
- }
-}
-
-// Reject any predicates that do not involve a type parameter.
-fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
- span: Span,
- predicates: &ty::GenericPredicates<'tcx>) {
- for predicate in &predicates.predicates {
- match predicate {
- &ty::Predicate::Trait(ty::Binder(ref tr)) => {
- let found_param = tr.input_types().iter()
- .flat_map(|ty| ty.walk())
- .any(is_ty_param);
- if !found_param { report_bound_error(tcx, span, tr.self_ty() )}
- }
- &ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(ty, _))) => {
- let found_param = ty.walk().any(|t| is_ty_param(t));
- if !found_param { report_bound_error(tcx, span, ty) }
- }
- _ => {}
- };
- }
-
- fn report_bound_error<'t>(tcx: &ty::ctxt<'t>,
- span: Span,
- bounded_ty: ty::Ty<'t>) {
- span_err!(tcx.sess, span, E0193,
- "cannot bound type `{}`, where clause \
- bounds may only be attached to types involving \
- type parameters",
- bounded_ty)
- }
-
- fn is_ty_param(ty: ty::Ty) -> bool {
- match &ty.sty {
- &ty::TyParam(_) => true,
- _ => false
- }
- }
-}
-
-fn reject_shadowing_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>,
- span: Span,
- generics: &ty::Generics<'tcx>) {
- let impl_params = generics.types.get_slice(subst::TypeSpace).iter()
- .map(|tp| tp.name).collect::<HashSet<_>>();
-
- for method_param in generics.types.get_slice(subst::FnSpace) {
- if impl_params.contains(&method_param.name) {
- wfcheck::error_194(tcx, span, method_param.name);
- }
- }
-}
-
-impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
- fn visit_item(&mut self, i: &hir::Item) {
- self.check_item_well_formed(i);
- intravisit::walk_item(self, i);
- }
-
- fn visit_fn(&mut self,
- fk: FnKind<'v>, fd: &'v hir::FnDecl,
- b: &'v hir::Block, span: Span, id: ast::NodeId) {
- match fk {
- FnKind::Closure | FnKind::ItemFn(..) => {}
- FnKind::Method(..) => {
- match self.tcx().impl_or_trait_item(self.tcx().map.local_def_id(id)) {
- ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
- reject_shadowing_type_parameters(self.tcx(), span, &ty_method.generics)
- }
- _ => {}
- }
- }
- }
- intravisit::walk_fn(self, fk, fd, b, span)
- }
-
- fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
- if let hir::MethodTraitItem(_, None) = trait_item.node {
- match self.tcx().impl_or_trait_item(self.tcx().map.local_def_id(trait_item.id)) {
- ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
- reject_non_type_param_bounds(
- self.tcx(),
- trait_item.span,
- &ty_method.predicates);
- reject_shadowing_type_parameters(
- self.tcx(),
- trait_item.span,
- &ty_method.generics);
- }
- _ => {}
- }
- }
-
- intravisit::walk_trait_item(self, trait_item)
- }
-}
-
-pub struct BoundsChecker<'cx,'tcx:'cx> {
- fcx: &'cx FnCtxt<'cx,'tcx>,
- span: Span,
-
- scope: region::CodeExtent,
-
- binding_count: usize,
- cache: Option<&'cx mut HashSet<Ty<'tcx>>>,
-}
-
-impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
- pub fn new(fcx: &'cx FnCtxt<'cx,'tcx>,
- scope: ast::NodeId,
- cache: Option<&'cx mut HashSet<Ty<'tcx>>>)
- -> BoundsChecker<'cx,'tcx> {
- let scope = fcx.tcx().region_maps.item_extent(scope);
- BoundsChecker { fcx: fcx, span: DUMMY_SP, scope: scope,
- cache: cache, binding_count: 0 }
- }
-
- /// Given a trait ref like `A : Trait<B>`, where `Trait` is defined as (say):
- ///
- /// trait Trait<B:OtherTrait> : Copy { ... }
- ///
- /// This routine will check that `B : OtherTrait` and `A : Trait<B>`. It will also recursively
- /// check that the types `A` and `B` are well-formed.
- ///
- /// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated
- /// to the point where impl `A : Trait<B>` is implemented).
- pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, span: Span) {
- let trait_predicates = self.fcx.tcx().lookup_predicates(trait_ref.def_id);
-
- let bounds = self.fcx.instantiate_bounds(span,
- trait_ref.substs,
- &trait_predicates);
-
- self.fcx.add_obligations_for_parameters(
- traits::ObligationCause::new(
- span,
- self.fcx.body_id,
- traits::ItemObligation(trait_ref.def_id)),
- &bounds);
-
- for &ty in &trait_ref.substs.types {
- self.check_traits_in_ty(ty, span);
- }
- }
-
- fn check_traits_in_ty(&mut self, ty: Ty<'tcx>, span: Span) {
- self.span = span;
- // When checking types outside of a type def'n, we ignore
- // region obligations. See discussion below in fold_ty().
- self.binding_count += 1;
- ty.fold_with(self);
- self.binding_count -= 1;
- }
-}
-
-impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
- fn tcx(&self) -> &ty::ctxt<'tcx> {
- self.fcx.tcx()
- }
-
- fn fold_binder<T>(&mut self, binder: &ty::Binder<T>) -> ty::Binder<T>
- where T : TypeFoldable<'tcx>
- {
- self.binding_count += 1;
- let value = self.fcx.tcx().liberate_late_bound_regions(
- self.scope,
- binder);
- debug!("BoundsChecker::fold_binder: late-bound regions replaced: {:?} at scope: {:?}",
- value, self.scope);
- let value = value.fold_with(self);
- self.binding_count -= 1;
- ty::Binder(value)
- }
-
- fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- debug!("BoundsChecker t={:?}",
- t);
-
- match self.cache {
- Some(ref mut cache) => {
- if !cache.insert(t) {
- // Already checked this type! Don't check again.
- debug!("cached");
- return t;
- }
- }
- None => { }
- }
-
- match t.sty{
- ty::TyStruct(def, substs) |
- ty::TyEnum(def, substs) => {
- let type_predicates = def.predicates(self.fcx.tcx());
- let bounds = self.fcx.instantiate_bounds(self.span, substs,
- &type_predicates);
-
- if self.binding_count == 0 {
- self.fcx.add_obligations_for_parameters(
- traits::ObligationCause::new(self.span,
- self.fcx.body_id,
- traits::ItemObligation(def.did)),
- &bounds);
- } else {
- // There are two circumstances in which we ignore
- // region obligations.
- //
- // The first is when we are inside of a closure
- // type. This is because in that case the region
- // obligations for the parameter types are things
- // that the closure body gets to assume and the
- // caller must prove at the time of call. In other
- // words, if there is a type like `<'a, 'b> | &'a
- // &'b int |`, it is well-formed, and caller will
- // have to show that `'b : 'a` at the time of
- // call.
- //
- // The second is when we are checking for
- // well-formedness outside of a type def'n or fn
- // body. This is for a similar reason: in general,
- // we only do WF checking for regions in the
- // result of expressions and type definitions, so
- // to as allow for implicit where clauses.
- //
- // (I believe we should do the same for traits, but
- // that will require an RFC. -nmatsakis)
- let bounds = filter_to_trait_obligations(bounds);
- self.fcx.add_obligations_for_parameters(
- traits::ObligationCause::new(self.span,
- self.fcx.body_id,
- traits::ItemObligation(def.did)),
- &bounds);
- }
-
- self.fold_substs(substs);
- }
- _ => {
- super_fold_ty(self, t);
- }
- }
-
- t // we're not folding to produce a new type, so just return `t` here
- }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// ADT
-
-struct AdtVariant<'tcx> {
- fields: Vec<AdtField<'tcx>>,
-}
-
-struct AdtField<'tcx> {
- ty: Ty<'tcx>,
- span: Span,
-}
-
-fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- struct_def: &hir::VariantData)
- -> AdtVariant<'tcx> {
- let fields =
- struct_def.fields().iter()
- .map(|field| {
- let field_ty = fcx.tcx().node_id_to_type(field.node.id);
- let field_ty = fcx.instantiate_type_scheme(field.span,
- &fcx.inh
- .infcx
- .parameter_environment
- .free_substs,
- &field_ty);
- AdtField { ty: field_ty, span: field.span }
- })
- .collect();
- AdtVariant { fields: fields }
-}
-
-fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- enum_def: &hir::EnumDef)
- -> Vec<AdtVariant<'tcx>> {
- enum_def.variants.iter()
- .map(|variant| struct_variant(fcx, &variant.node.data))
- .collect()
-}
-
-fn filter_to_trait_obligations<'tcx>(bounds: ty::InstantiatedPredicates<'tcx>)
- -> ty::InstantiatedPredicates<'tcx>
-{
- let mut result = ty::InstantiatedPredicates::empty();
- for (space, _, predicate) in bounds.predicates.iter_enumerated() {
- match *predicate {
- ty::Predicate::Trait(..) |
- ty::Predicate::Projection(..) => {
- result.predicates.push(space, predicate.clone())
- }
- ty::Predicate::WellFormed(..) |
- ty::Predicate::ObjectSafe(..) |
- ty::Predicate::Equate(..) |
- ty::Predicate::TypeOutlives(..) |
- ty::Predicate::RegionOutlives(..) => {
- }
- }
- }
- result
-}
use std::cell::RefCell;
use std::collections::HashSet;
-use std::rc::Rc;
use syntax::ast;
use syntax::codemap::{Span};
use syntax::parse::token::{special_idents};
-> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
CheckTypeWellFormedVisitor {
ccx: ccx,
- code: traits::ObligationCauseCode::RFC1214(
- Rc::new(traits::ObligationCauseCode::MiscObligation))
+ code: traits::ObligationCauseCode::MiscObligation
}
}
ty::wf::trait_obligations(fcx.infcx(),
fcx.body_id,
&trait_ref,
- ast_trait_ref.path.span,
- true);
+ ast_trait_ref.path.span);
for obligation in obligations {
fcx.register_predicate(obligation);
}
.flat_map(|p| ty::wf::predicate_obligations(fcx.infcx(),
fcx.body_id,
p,
- span,
- true));
+ span));
for obligation in obligations {
fcx.register_predicate(obligation);
None => { }
}
}
- hir::ItemImpl(_, _, _, Some(_), ref self_ty, _) => {
+ hir::ItemImpl(_, _, _, Some(_), _, _) => {
let impl_def_id = self.tcx.map.local_def_id(item.id);
let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
let trait_def_id = trait_ref.def_id;
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
if !traits::is_object_safe(self.tcx, data.principal_def_id()) {
- // FIXME(#27579). This just means the
- // self-ty is illegal; WF will report this
- // error. But it will do so as a warning
- // for a release or two. For backwards
- // compat reasons, then, we continue to
- // report it here so that things which
- // were errors remain errors.
- span_err!(self.tcx.sess, self_ty.span, E0372,
- "the trait `{}` cannot be made into an object",
- self.tcx.item_path_str(data.principal_def_id()));
+ // This is an error, but it will be
+ // reported by wfcheck. Ignore it
+ // here. This is tested by
+ // `coherence-impl-trait-for-trait-object-safe.rs`.
} else {
let mut supertrait_def_ids =
traits::supertrait_def_ids(self.tcx, data.principal_def_id());
```
"##,
-E0372: r##"
-Trying to implement a trait for a trait object (as in `impl Trait1 for
-Trait2 { ... }`) does not work if the trait is not object-safe. Please see the
-[RFC 255] for more details on object safety rules.
-
-[RFC 255]: https://github.com/rust-lang/rfcs/pull/255
-"##,
-
E0379: r##"
Trait methods cannot be declared `const` by design. For more information, see
[RFC 911].
// E0319, // trait impls for defaulted traits allowed just for structs/enums
E0320, // recursive overflow during dropck
E0328, // cannot implement Unsize explicitly
+// E0372, // coherence not object safe
E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with one field being coerced, none found
E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
coherence::check_coherence(&ccx));
});
- time(time_passes, "wf checking (old)", ||
- check::check_wf_old(&ccx));
+ time(time_passes, "wf checking", ||
+ check::check_wf_new(&ccx));
time(time_passes, "item-types checking", ||
check::check_item_types(&ccx));
time(time_passes, "drop-impl checking", ||
check::check_drop_impls(&ccx));
- // Do this last so that if there are errors in the old code, they
- // get reported, and we don't get extra warnings.
- time(time_passes, "wf checking (new)", ||
- check::check_wf_new(&ccx));
-
check_for_entry_fn(&ccx);
tcx.sess.abort_if_errors();
}
use iter::Iterator;
use libc;
use mem;
+use memchr;
use ops::Deref;
use option::Option::{self, Some, None};
use os::raw::c_char;
}
fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
- match bytes.iter().position(|x| *x == 0) {
+ match memchr::memchr(0, &bytes) {
Some(i) => Err(NulError(i, bytes)),
None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
}
use error;
use fmt;
use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom};
+use memchr;
/// The `BufReader` struct adds buffering to any reader.
///
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Write for LineWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- match buf.iter().rposition(|b| *b == b'\n') {
+ match memchr::memrchr(b'\n', buf) {
Some(i) => {
let n = try!(self.inner.write(&buf[..i + 1]));
if n != i + 1 { return Ok(n) }
use string::String;
use str;
use vec::Vec;
+use memchr;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::{BufReader, BufWriter, LineWriter};
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e)
};
- match available.iter().position(|x| *x == delim) {
+ match memchr::memchr(delim, available) {
Some(i) => {
buf.extend_from_slice(&available[..i + 1]);
(true, i + 1)
#![feature(link_args)]
#![feature(linkage)]
#![feature(macro_reexport)]
+#![feature(num_bits_bytes)]
#![feature(on_unimplemented)]
#![feature(oom)]
#![feature(optin_builtin_traits)]
pub mod process;
pub mod sync;
pub mod time;
+mod memchr;
#[macro_use]
#[path = "sys/common/mod.rs"] mod sys_common;
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// Original implementation taken from rust-memchr
+// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
+
+
+
+/// A safe interface to `memchr`.
+///
+/// Returns the index corresponding to the first occurrence of `needle` in
+/// `haystack`, or `None` if one is not found.
+///
+/// memchr reduces to super-optimized machine code at around an order of
+/// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
+/// (See benchmarks.)
+///
+/// # Example
+///
+/// This shows how to find the first position of a byte in a byte string.
+///
+/// ```rust,ignore
+/// use memchr::memchr;
+///
+/// let haystack = b"the quick brown fox";
+/// assert_eq!(memchr(b'k', haystack), Some(8));
+/// ```
+pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+ // libc memchr
+ #[cfg(not(target_os = "windows"))]
+ fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+ use libc;
+
+ let p = unsafe {
+ libc::memchr(
+ haystack.as_ptr() as *const libc::c_void,
+ needle as libc::c_int,
+ haystack.len() as libc::size_t)
+ };
+ if p.is_null() {
+ None
+ } else {
+ Some(p as usize - (haystack.as_ptr() as usize))
+ }
+ }
+
+ // use fallback on windows, since it's faster
+ #[cfg(target_os = "windows")]
+ fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+ fallback::memchr(needle, haystack)
+ }
+
+ memchr_specific(needle, haystack)
+}
+
+/// A safe interface to `memrchr`.
+///
+/// Returns the index corresponding to the last occurrence of `needle` in
+/// `haystack`, or `None` if one is not found.
+///
+/// # Example
+///
+/// This shows how to find the last position of a byte in a byte string.
+///
+/// ```rust,ignore
+/// use memchr::memrchr;
+///
+/// let haystack = b"the quick brown fox";
+/// assert_eq!(memrchr(b'o', haystack), Some(17));
+/// ```
+pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+
+ #[cfg(target_os = "linux")]
+ fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+ use libc;
+
+ // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
+ if haystack.is_empty() {return None}
+ let p = unsafe {
+ libc::memrchr(
+ haystack.as_ptr() as *const libc::c_void,
+ needle as libc::c_int,
+ haystack.len() as libc::size_t)
+ };
+ if p.is_null() {
+ None
+ } else {
+ Some(p as usize - (haystack.as_ptr() as usize))
+ }
+ }
+
+ #[cfg(not(target_os = "linux"))]
+ fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+ haystack.iter().rposition(|&b| b == needle)
+ }
+
+ memrchr_specific(needle, haystack)
+}
+
+#[allow(dead_code)]
+mod fallback {
+ use cmp;
+ use usize;
+
+ const LO_U64: u64 = 0x0101010101010101;
+ const HI_U64: u64 = 0x8080808080808080;
+
+ // use truncation
+ const LO_USIZE: usize = LO_U64 as usize;
+ const HI_USIZE: usize = HI_U64 as usize;
+
+ /// Return `true` if `x` contains any zero byte.
+ ///
+ /// From *Matters Computational*, J. Arndt
+ ///
+ /// "The idea is to subtract one from each of the bytes and then look for
+ /// bytes where the borrow propagated all the way to the most significant
+ /// bit."
+ #[inline]
+ fn contains_zero_byte(x: usize) -> bool {
+ x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ #[inline]
+ fn repeat_byte(b: u8) -> usize {
+ let mut rep = (b as usize) << 8 | b as usize;
+ rep = rep << 16 | rep;
+ rep
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ #[inline]
+ fn repeat_byte(b: u8) -> usize {
+ let mut rep = (b as usize) << 8 | b as usize;
+ rep = rep << 16 | rep;
+ rep = rep << 32 | rep;
+ rep
+ }
+
+ /// Return the first index matching the byte `a` in `text`.
+ pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
+ // Scan for a single byte value by reading two `usize` words at a time.
+ //
+ // Split `text` in three parts
+ // - unaligned inital part, before the first word aligned address in text
+ // - body, scan by 2 words at a time
+ // - the last remaining part, < 2 word size
+ let len = text.len();
+ let ptr = text.as_ptr();
+
+ // search up to an aligned boundary
+ let align = (ptr as usize) & (usize::BYTES- 1);
+ let mut offset;
+ if align > 0 {
+ offset = cmp::min(usize::BYTES - align, len);
+ if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
+ return Some(index);
+ }
+ } else {
+ offset = 0;
+ }
+
+ // search the body of the text
+ let repeated_x = repeat_byte(x);
+
+ if len >= 2 * usize::BYTES {
+ while offset <= len - 2 * usize::BYTES {
+ unsafe {
+ let u = *(ptr.offset(offset as isize) as *const usize);
+ let v = *(ptr.offset((offset + usize::BYTES) as isize) as *const usize);
+
+ // break if there is a matching byte
+ let zu = contains_zero_byte(u ^ repeated_x);
+ let zv = contains_zero_byte(v ^ repeated_x);
+ if zu || zv {
+ break;
+ }
+ }
+ offset += usize::BYTES * 2;
+ }
+ }
+
+ // find the byte after the point the body loop stopped
+ text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
+ }
+
+ /// Return the last index matching the byte `a` in `text`.
+ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
+ // Scan for a single byte value by reading two `usize` words at a time.
+ //
+ // Split `text` in three parts
+ // - unaligned tail, after the last word aligned address in text
+ // - body, scan by 2 words at a time
+ // - the first remaining bytes, < 2 word size
+ let len = text.len();
+ let ptr = text.as_ptr();
+
+ // search to an aligned boundary
+ let end_align = (ptr as usize + len) & (usize::BYTES - 1);
+ let mut offset;
+ if end_align > 0 {
+ offset = len - cmp::min(usize::BYTES - end_align, len);
+ if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
+ return Some(offset + index);
+ }
+ } else {
+ offset = len;
+ }
+
+ // search the body of the text
+ let repeated_x = repeat_byte(x);
+
+ while offset >= 2 * usize::BYTES {
+ unsafe {
+ let u = *(ptr.offset(offset as isize - 2 * usize::BYTES as isize) as *const usize);
+ let v = *(ptr.offset(offset as isize - usize::BYTES as isize) as *const usize);
+
+ // break if there is a matching byte
+ let zu = contains_zero_byte(u ^ repeated_x);
+ let zv = contains_zero_byte(v ^ repeated_x);
+ if zu || zv {
+ break;
+ }
+ }
+ offset -= 2 * usize::BYTES;
+ }
+
+ // find the byte before the point the body loop stopped
+ text[..offset].iter().rposition(|elt| *elt == x)
+ }
+
+ // test fallback implementations on all plattforms
+ #[test]
+ fn matches_one() {
+ assert_eq!(Some(0), memchr(b'a', b"a"));
+ }
+
+ #[test]
+ fn matches_begin() {
+ assert_eq!(Some(0), memchr(b'a', b"aaaa"));
+ }
+
+ #[test]
+ fn matches_end() {
+ assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
+ }
+
+ #[test]
+ fn matches_nul() {
+ assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
+ }
+
+ #[test]
+ fn matches_past_nul() {
+ assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
+ }
+
+ #[test]
+ fn no_match_empty() {
+ assert_eq!(None, memchr(b'a', b""));
+ }
+
+ #[test]
+ fn no_match() {
+ assert_eq!(None, memchr(b'a', b"xyz"));
+ }
+
+ #[test]
+ fn matches_one_reversed() {
+ assert_eq!(Some(0), memrchr(b'a', b"a"));
+ }
+
+ #[test]
+ fn matches_begin_reversed() {
+ assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
+ }
+
+ #[test]
+ fn matches_end_reversed() {
+ assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
+ }
+
+ #[test]
+ fn matches_nul_reversed() {
+ assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
+ }
+
+ #[test]
+ fn matches_past_nul_reversed() {
+ assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
+ }
+
+ #[test]
+ fn no_match_empty_reversed() {
+ assert_eq!(None, memrchr(b'a', b""));
+ }
+
+ #[test]
+ fn no_match_reversed() {
+ assert_eq!(None, memrchr(b'a', b"xyz"));
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ // test the implementations for the current plattform
+ use super::{memchr, memrchr};
+
+ #[test]
+ fn matches_one() {
+ assert_eq!(Some(0), memchr(b'a', b"a"));
+ }
+
+ #[test]
+ fn matches_begin() {
+ assert_eq!(Some(0), memchr(b'a', b"aaaa"));
+ }
+
+ #[test]
+ fn matches_end() {
+ assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
+ }
+
+ #[test]
+ fn matches_nul() {
+ assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
+ }
+
+ #[test]
+ fn matches_past_nul() {
+ assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
+ }
+
+ #[test]
+ fn no_match_empty() {
+ assert_eq!(None, memchr(b'a', b""));
+ }
+
+ #[test]
+ fn no_match() {
+ assert_eq!(None, memchr(b'a', b"xyz"));
+ }
+
+ #[test]
+ fn matches_one_reversed() {
+ assert_eq!(Some(0), memrchr(b'a', b"a"));
+ }
+
+ #[test]
+ fn matches_begin_reversed() {
+ assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
+ }
+
+ #[test]
+ fn matches_end_reversed() {
+ assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
+ }
+
+ #[test]
+ fn matches_nul_reversed() {
+ assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
+ }
+
+ #[test]
+ fn matches_past_nul_reversed() {
+ assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
+ }
+
+ #[test]
+ fn no_match_empty_reversed() {
+ assert_eq!(None, memrchr(b'a', b""));
+ }
+
+ #[test]
+ fn no_match_reversed() {
+ assert_eq!(None, memrchr(b'a', b"xyz"));
+ }
+}
use fmt;
use io::{self, Error, ErrorKind};
use path;
+use str;
use sys::pipe::{self, AnonPipe};
use sys::process as imp;
use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
pub stderr: Vec<u8>,
}
+// If either stderr or stdout are valid utf8 strings it prints the valid
+// strings, otherwise it prints the byte sequence instead
+#[stable(feature = "process_output_debug", since = "1.7.0")]
+impl fmt::Debug for Output {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+
+ let stdout_utf8 = str::from_utf8(&self.stdout);
+ let stdout_debug: &fmt::Debug = match stdout_utf8 {
+ Ok(ref str) => str,
+ Err(_) => &self.stdout
+ };
+
+ let stderr_utf8 = str::from_utf8(&self.stderr);
+ let stderr_debug: &fmt::Debug = match stderr_utf8 {
+ Ok(ref str) => str,
+ Err(_) => &self.stderr
+ };
+
+ fmt.debug_struct("Output")
+ .field("status", &self.status)
+ .field("stdout", stdout_debug)
+ .field("stderr", stderr_debug)
+ .finish()
+ }
+}
+
/// Describes what to do with a standard I/O stream for a child process.
#[stable(feature = "process", since = "1.0.0")]
pub struct Stdio(StdioImp);
//! if the entropy pool is very small, such as immediately after first booting.
//! Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy
//! pool is not initialized yet, but it does not block once initialized.
+//! `getrandom(2)` was based on `getentropy(2)`, an existing system call in OpenBSD.
//! `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
//! If an application does not have `getrandom` and likely to be run soon after first booting,
//! or on a system with very few entropy sources, one should consider using `/dev/random` via
pub use self::imp::OsRng;
-#[cfg(all(unix, not(target_os = "ios")))]
+#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
mod imp {
use self::OsRngInner::*;
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
+ /// - OpenBSD: uses the `getentropy(2)` system call.
///
/// This does not block.
pub struct OsRng {
}
}
+#[cfg(target_os = "openbsd")]
+mod imp {
+ use io;
+ use mem;
+ use libc::c_long;
+ use sys::os::errno;
+ use rand::Rng;
+
+ /// A random number generator that retrieves randomness straight from
+ /// the operating system. Platform sources:
+ ///
+ /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+ /// `/dev/urandom`, or from `getrandom(2)` system call if available.
+ /// - Windows: calls `CryptGenRandom`, using the default cryptographic
+ /// service provider with the `PROV_RSA_FULL` type.
+ /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
+ /// - OpenBSD: uses the `getentropy(2)` system call.
+ ///
+ /// This does not block.
+ pub struct OsRng {
+ // dummy field to ensure that this struct cannot be constructed outside
+ // of this module
+ _dummy: (),
+ }
+
+ impl OsRng {
+ /// Create a new `OsRng`.
+ pub fn new() -> io::Result<OsRng> {
+ Ok(OsRng { _dummy: () })
+ }
+ }
+
+ impl Rng for OsRng {
+ fn next_u32(&mut self) -> u32 {
+ let mut v = [0; 4];
+ self.fill_bytes(&mut v);
+ unsafe { mem::transmute(v) }
+ }
+ fn next_u64(&mut self) -> u64 {
+ let mut v = [0; 8];
+ self.fill_bytes(&mut v);
+ unsafe { mem::transmute(v) }
+ }
+ fn fill_bytes(&mut self, v: &mut [u8]) {
+ // getentropy(2) permits a maximum buffer size of 256 bytes
+ for s in v.chunks_mut(256) {
+ let ret = unsafe {
+ libc::syscall(libc::NR_GETENTROPY, s.as_mut_ptr(), s.len())
+ };
+ if ret == -1 {
+ panic!("unexpected getentropy error: {}", errno());
+ }
+ }
+ }
+ }
+}
+
#[cfg(target_os = "ios")]
mod imp {
#[cfg(stage0)] use prelude::v1::*;
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
+ /// - OpenBSD: uses the `getentropy(2)` system call.
///
/// This does not block.
pub struct OsRng {
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
+ /// - OpenBSD: uses the `getentropy(2)` system call.
///
/// This does not block.
pub struct OsRng {
fn next(&mut self) -> Option<io::Result<DirEntry>> {
extern {
- fn rust_dirent_t_size() -> c_int;
+ fn rust_dirent_t_size() -> libc::size_t;
}
let mut buf: Vec<u8> = Vec::with_capacity(unsafe {
- rust_dirent_t_size() as usize
+ rust_dirent_t_size()
});
let ptr = buf.as_mut_ptr() as *mut libc::dirent;
use iter;
use libc::{self, c_int, c_char, c_void};
use mem;
+use memchr;
use path::{self, PathBuf};
use ptr;
use slice;
if input.is_empty() {
return None;
}
- let pos = input[1..].iter().position(|&b| b == b'=').map(|p| p + 1);
+ let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
pos.map(|p| (
OsStringExt::from_vec(input[..p].to_vec()),
OsStringExt::from_vec(input[p+1..].to_vec()),
ExprLit(P<Lit>),
/// A cast (`foo as f64`)
ExprCast(P<Expr>, P<Ty>),
+ ExprType(P<Expr>, P<Ty>),
/// An `if` block, with an optional else block
///
/// `if expr { block } else { expr }`
// Allows `#[deprecated]` attribute
("deprecated", "1.6.0", Some(29935), Active),
+
+ // allow using type ascription in expressions
+ ("type_ascription", "1.6.0", Some(23416), Active),
];
// (changing above list without updating src/doc/reference.md makes @cmr sad)
"box expression syntax is experimental; \
you can call `Box::new` instead.");
}
+ ast::ExprType(..) => {
+ self.gate_feature("type_ascription", e.span,
+ "type ascription is experimental");
+ }
_ => {}
}
visit::walk_expr(self, e);
ExprCast(expr, ty) => {
ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
}
+ ExprType(expr, ty) => {
+ ExprType(folder.fold_expr(expr), folder.fold_ty(ty))
+ }
ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
ExprIf(cond, tr, fl) => {
ExprIf(folder.fold_expr(cond),
use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
use ast::{ExprMethodCall, ExprParen, ExprPath};
-use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
+use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprType, ExprUnary};
use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, FunctionRetTy};
use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
ExprCast(lhs, rhs), None);
continue
+ } else if op == AssocOp::Colon {
+ let rhs = try!(self.parse_ty());
+ lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
+ ExprType(lhs, rhs), None);
+ continue
} else if op == AssocOp::DotDot {
// If we didn’t have to handle `x..`, it would be pretty easy to generalise
// it to the Fixity::None code.
break
}
-
let rhs = try!(match op.fixity() {
Fixity::Right => self.with_res(restrictions, |this|{
this.parse_assoc_expr_with(op.precedence(), LhsExpr::NotYetParsed)
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
}
- AssocOp::As | AssocOp::DotDot => self.bug("As or DotDot branch reached")
+ AssocOp::As | AssocOp::Colon | AssocOp::DotDot => {
+ self.bug("As, Colon or DotDot branch reached")
+ }
};
if op.fixity() == Fixity::None { break }
ast::ExprAssign(..) | ast::ExprBinary(..) |
ast::ExprClosure(..) |
ast::ExprAssignOp(..) | ast::ExprCast(..) |
- ast::ExprInPlace(..) => true,
+ ast::ExprInPlace(..) | ast::ExprType(..) => true,
_ => false,
}
}
try!(self.word_space("as"));
try!(self.print_type(&**ty));
}
+ ast::ExprType(ref expr, ref ty) => {
+ try!(self.print_expr(&**expr));
+ try!(self.word_space(":"));
+ try!(self.print_type(&**ty));
+ }
ast::ExprIf(ref test, ref blk, ref elseopt) => {
try!(self.print_if(&**test, &**blk, elseopt.as_ref().map(|e| &**e)));
}
/// `as`
As,
/// `..` range
- DotDot
+ DotDot,
+ /// `:`
+ Colon,
}
#[derive(Debug, PartialEq, Eq)]
Token::AndAnd => Some(LAnd),
Token::OrOr => Some(LOr),
Token::DotDot => Some(DotDot),
+ Token::Colon => Some(Colon),
_ if t.is_keyword(keywords::As) => Some(As),
_ => None
}
pub fn precedence(&self) -> usize {
use self::AssocOp::*;
match *self {
- As => 14,
+ As | Colon => 14,
Multiply | Divide | Modulus => 13,
Add | Subtract => 12,
ShiftLeft | ShiftRight => 11,
Inplace | Assign | AssignOp(_) => Fixity::Right,
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd |
BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual |
- LAnd | LOr => Fixity::Left,
+ LAnd | LOr | Colon => Fixity::Left,
DotDot => Fixity::None
}
}
match *self {
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
- ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot => false
+ ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot | Colon => false
}
}
Assign | AssignOp(_) | Inplace => true,
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
- LOr | DotDot => false
+ LOr | DotDot | Colon => false
}
}
BitOr => Some(ast::BiBitOr),
LAnd => Some(ast::BiAnd),
LOr => Some(ast::BiOr),
- Inplace | Assign | AssignOp(_) | As | DotDot => None
+ Inplace | Assign | AssignOp(_) | As | DotDot | Colon => None
}
}
-
}
visitor.visit_expr(subexpression)
}
ExprLit(_) => {}
- ExprCast(ref subexpression, ref typ) => {
+ ExprCast(ref subexpression, ref typ) | ExprType(ref subexpression, ref typ) => {
visitor.visit_expr(subexpression);
visitor.visit_ty(typ)
}
use syntax::ext::base;
use syntax::ext::base::*;
use syntax::feature_gate;
-use syntax::parse::token::{intern, InternedString};
-use syntax::parse::token;
+use syntax::parse::token::intern;
+use syntax::parse::{self, token};
use syntax::ptr::P;
use syntax::ast::AsmDialect;
return DummyResult::expr(sp);
}
- let mut p = cx.new_parser_from_tts(tts);
- let mut asm = InternedString::new("");
+ // Split the tts before the first colon, to avoid `asm!("x": y)` being
+ // parsed as `asm!(z)` with `z = "x": y` which is type ascription.
+ let first_colon = tts.iter().position(|tt| {
+ match *tt {
+ ast::TokenTree::Token(_, token::Colon) |
+ ast::TokenTree::Token(_, token::ModSep) => true,
+ _ => false
+ }
+ }).unwrap_or(tts.len());
+ let mut p = cx.new_parser_from_tts(&tts[first_colon..]);
+ let mut asm = token::InternedString::new("");
let mut asm_str_style = None;
let mut outputs = Vec::new();
let mut inputs = Vec::new();
cx.span_err(sp, "malformed inline assembly");
return DummyResult::expr(sp);
}
- let (s, style) = match expr_to_string(cx, panictry!(p.parse_expr()),
+ // Nested parser, stop before the first colon (see above).
+ let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]);
+ let (s, style) = match expr_to_string(cx, panictry!(p2.parse_expr()),
"inline assembly must be a string literal") {
Some((s, st)) => (s, st),
// let compilation continue
None => return DummyResult::expr(sp),
};
+
+ // This is most likely malformed.
+ if p2.token != token::Eof {
+ let mut extra_tts = panictry!(p2.parse_all_token_trees());
+ extra_tts.extend(tts[first_colon..].iter().cloned());
+ p = parse::tts_to_parser(cx.parse_sess, extra_tts, cx.cfg());
+ }
+
asm = s;
asm_str_style = Some(style);
}
let message = format!("Usage: {} [OPTIONS] [FILTER]", binary);
println!(r#"{usage}
-The FILTER regex is tested against the name of all tests to run, and
-only those tests that match are run.
+The FILTER string is tested against the name of all tests, and only those
+tests whose names contain the filter are run.
By default, all tests are run in parallel. This can be altered with the
RUST_TEST_THREADS environment variable when running tests (set it to 1).
return readdir_r(dirp, entry, result);
}
-int
+size_t
rust_dirent_t_size() {
return sizeof(struct dirent);
}
#![crate_type="lib"]
-pub trait Bar {
+pub trait Bar: Sized {
type T;
fn get(x: Option<Self>) -> <Self as Bar>::T;
#![crate_name="static_methods_crate"]
#![crate_type = "lib"]
-pub trait read {
+pub trait read: Sized {
fn readMaybe(s: String) -> Option<Self>;
}
trait Other {
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
- // (note that we no longer catch the error here, since the
- // error below aborts compilation.
- // See also associated-types-no-suitable-supertrait-2.rs
- // which checks that this error would be caught eventually.)
+ //~^ ERROR the trait `Get` is not implemented for the type `Self`
}
impl<T:Get> Other for T {
use std::sync::mpsc::{channel, Sender};
-trait Foo : Sync+'static {
+trait Foo : Sized+Sync+'static {
fn foo(self, mut chan: Sender<Self>) { }
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// A version of coerce-expect-unsized that uses type ascription.
+// Doesn't work so far, but supposed to work eventually
+
+#![feature(box_syntax, type_ascription)]
+
+use std::fmt::Debug;
+
+pub fn main() {
+ let _ = box { [1, 2, 3] }: Box<[i32]>; //~ ERROR mismatched types
+ let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; //~ ERROR mismatched types
+ let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>;
+ //~^ ERROR mismatched types
+ let _ = box { |x| (x as u8) }: Box<Fn(i32) -> _>; //~ ERROR mismatched types
+ let _ = box if true { false } else { true }: Box<Debug>; //~ ERROR mismatched types
+ let _ = box match true { true => 'a', false => 'b' }: Box<Debug>; //~ ERROR mismatched types
+
+ let _ = &{ [1, 2, 3] }: &[i32]; //~ ERROR mismatched types
+ let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; //~ ERROR mismatched types
+ let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32];
+ //~^ ERROR mismatched types
+ let _ = &{ |x| (x as u8) }: &Fn(i32) -> _; //~ ERROR mismatched types
+ let _ = &if true { false } else { true }: &Debug; //~ ERROR mismatched types
+ let _ = &match true { true => 'a', false => 'b' }: &Debug; //~ ERROR mismatched types
+
+ let _ = Box::new([1, 2, 3]): Box<[i32]>; //~ ERROR mismatched types
+ let _ = Box::new(|x| (x as u8)): Box<Fn(i32) -> _>; //~ ERROR mismatched types
+
+ let _ = vec![
+ Box::new(|x| (x as u8)),
+ box |x| (x as i16 as u8),
+ ]: Vec<Box<Fn(i32) -> _>>;
+}
// 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
- fn eq(&self, other: &Self) { panic!(); }
-}
+trait NotObjectSafe { fn eq(&self, other: Self); }
+impl NotObjectSafe for NotObjectSafe { } //~ ERROR E0038
fn main() { }
trait Bar<X> { }
-fn vacuous<A>()
+// We don't always check where clauses for sanity, but in this case
+// wfcheck does report an error here:
+fn vacuous<A>() //~ ERROR the trait `Bar<u32>` is not implemented for the type `i32`
where i32: Foo<u32, A>
{
- // vacuous could never be called, because it requires that i32:
- // Bar<u32>. But the code doesn't check that this could never be
- // satisfied.
+ // ... the original intention was to check that we don't use that
+ // vacuous where clause (which could never be satisfied) to accept
+ // the following line and then mess up calls elsewhere.
require::<i32, u32>();
- //~^ ERROR the trait `Bar<u32>` is not implemented for the type `i32`
}
fn require<A,B>()
trait FromStructReader<'a> { }
trait ResponseHook {
- fn get<'a, T: FromStructReader<'a>>(&'a self);
+ fn get(&self);
}
fn foo(res : Box<ResponseHook>) { res.get } //~ ERROR attempted to take value of method
fn main() {}
}
trait Graph<N: Node> {
- fn nodes<'a, I: Iterator<Item=&'a N>>(&'a self) -> I;
+ fn nodes<'a, I: Iterator<Item=&'a N>>(&'a self) -> I
+ where N: 'a;
}
impl<N: Node> Graph<N> for Vec<N> {
- fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I {
+ fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
+ where N: 'a
+ {
self.iter() //~ ERROR mismatched types
}
}
trait Str {}
-trait Something {
+trait Something: Sized {
fn yay<T: Debug>(_: Option<Self>, thing: &[T]);
}
#[inline(never)]
fn foo(b: &Bar) {
+ //~^ ERROR E0038
b.foo(&0)
- //~^ ERROR the trait `Foo` is not implemented for the type `Bar`
- //~| ERROR E0038
- //~| WARNING E0038
}
fn main() {
let mut thing = Thing;
- let test: &Bar = &mut thing; //~ ERROR E0038
+ let test: &Bar = &mut thing;
foo(test);
}
struct Bar {
foos: &'static [&'static (Qiz + 'static)]
+//~^ ERROR E0038
}
const FOO : Foo = Foo;
const BAR : Bar = Bar { foos: &[&FOO]};
-//~^ ERROR E0038
fn main() { }
}
trait To {
- fn to<Dst>(
- self //~ error: the trait `core::marker::Sized` is not implemented
+ fn to<Dst>( //~ ERROR the trait `core::marker::Sized` is not implemented
+ self
) -> <Dst as From<Self>>::Result where Dst: From<Self> {
- From::from( //~ error: the trait `core::marker::Sized` is not implemented
- //~^ ERROR E0277
- self
- )
+ From::from(self)
}
}
fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
// Not obvious, but there is an implicit lifetime here -------^
//~^^ ERROR cannot infer
+ //~| ERROR cannot infer
+ //~| ERROR cannot infer
//
// The fact that `Publisher` is using an implicit lifetime is
// what was causing the debruijn accounting to be off, so
fn foo(self);
}
-fn foo<'a,'b,T>(x: &'a T, y: &'b T)
+fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required
where &'a T : Foo,
&'b T : Foo
{
- x.foo(); //~ ERROR type annotations required
+ x.foo();
y.foo();
}
{
fn bar(x:i32) ->i32 { 3*x };
let b:Box<Any> = Box::new(bar as fn(_)->_);
- b.downcast_ref::<fn(_)->_>(); //~ ERROR E0101
+ b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
}
}
impl ToNbt<Self> {} //~ ERROR use of `Self` outside of an impl or trait
-//~^ WARNING the trait `ToNbt` cannot be made into an object
+//~^ ERROR the trait `ToNbt` cannot be made into an object
fn main() {}
}
fn bar(_x: Foo) {}
-//~^ ERROR E0277
+//~^ ERROR E0038
fn main() {}
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
- t
//~^ ERROR E0038
//~| NOTE method `bar` has generic type parameters
+ t
}
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
t as &Bar
- //~^ ERROR E0038
- //~| NOTE method `bar` has generic type parameters
- //~| ERROR E0038
}
fn make_quux<T:Quux>(t: &T) -> &Quux {
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
- t
- //~^ ERROR E0038
- //~| NOTE method `bar` references the `Self` type in its arguments or return type
-}
-
-fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
- t as &Bar
//~^ ERROR E0038
//~| NOTE method `bar` references the `Self` type in its arguments or return type
- //~| ERROR E0038
+ loop { }
}
fn make_baz<T:Baz>(t: &T) -> &Baz {
- t
//~^ ERROR E0038
//~| NOTE method `bar` references the `Self` type in its arguments or return type
-}
-
-fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
- t as &Baz
- //~^ ERROR E0038
- //~| NOTE method `bar` references the `Self` type in its arguments or return type
- //~| ERROR E0038
+ t
}
fn make_quux<T:Quux>(t: &T) -> &Quux {
}
fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
- b
- //~^ ERROR E0038
- //~| NOTE method `foo` has no receiver
-}
-
-fn foo_explicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
- b as Box<Foo>
- //~^ ERROR E0038
- //~| NOTE method `foo` has no receiver
- //~| ERROR E0038
+ //~^ ERROR E0038
+ loop { }
}
fn main() {
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
- t
//~^ ERROR E0038
- //~| NOTE the trait cannot require that `Self : Sized`
-}
-
-fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
- t as &Bar
- //~^ ERROR E0038
- //~| NOTE the trait cannot require that `Self : Sized`
- //~| ERROR E0038
+ loop { }
}
fn main() {
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
- t
- //~^ ERROR E0038
- //~| NOTE the trait cannot require that `Self : Sized`
-}
-
-fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
- t as &Bar
//~^ ERROR E0038
//~| NOTE the trait cannot require that `Self : Sized`
- //~| ERROR E0038
+ t
}
fn main() {
// oh dear!
box B(&*v) as Box<X>
//~^ ERROR the parameter type `T` may not live long enough
- //~| WARNING the parameter type `T` may not live long enough
- //~| WARNING the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
- //~| WARNING the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests that callees correctly infer an ordering between free regions
+// that appear in their parameter list. See also
+// regions-free-region-ordering-caller.rs
+
+fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
+ //~^ ERROR reference has a longer lifetime than the data it references
+ // Do not infer ordering from closure argument types.
+ let z: Option<&'a &'b usize> = None;
+}
+
+fn main() {}
panic!();
}
-fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
- // Do not infer ordering from closure argument types.
- let z: Option<&'a &'b usize> = None;
- //~^ ERROR reference has a longer lifetime than the data it references
-}
+// see regions-free-region-ordering-callee-4.rs
fn ordering5<'a, 'b>(a: &'a usize, b: &'b usize, x: Option<&'a &'b usize>) {
let z: Option<&'a &'b usize> = None;
type Foo;
}
-fn wf<T>() { }
-
-// As a side-effect of the conservative process above, this argument
-// is not automatically considered well-formed, since for it to be WF,
-// we would need to know that `'y: 'x`, but we do not infer that.
-fn callee<'x, 'y, T>(
- t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-{
- wf::<&'x &'y i32>();
+// As a side-effect of the conservative process above, the type of
+// this argument `t` is not automatically considered well-formed,
+// since for it to be WF, we would need to know that `'y: 'x`, but we
+// do not infer that.
+fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
//~^ ERROR reference has a longer lifetime than the data it references
+{
}
fn main() { }
trait TheTrait<'t>: 't { }
struct Foo<'a,'b> {
- x: Box<TheTrait<'a>+'b>
- //~^ ERROR reference has a longer lifetime
+ x: Box<TheTrait<'a>+'b> //~ ERROR E0478
}
fn main() { }
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that an RFC1214 warning from an earlier function (`foo`) does
-// not suppress an error for the same problem (`WantEq<NotEq>`,
-// `NotEq: !Eq`) in a later function (`bar)`. Earlier versions of the
-// warning mechanism had an issue due to caching.
-
-#![allow(dead_code)]
-#![allow(unused_variables)]
-
-struct WantEq<T:Eq> { t: T }
-
-struct NotEq;
-
-trait Trait<T> { }
-
-fn foo() {
- let x: Box<Trait<WantEq<NotEq>>> = loop { };
- //~^ WARN E0277
-}
-
-fn bar() {
- wf::<WantEq<NotEq>>();
- //~^ ERROR E0277
-}
-
-fn wf<T>() { }
-
-fn main() { }
fn next(&mut self) -> Option<A>;
}
-trait IteratorUtil<A>
+trait IteratorUtil<A>: Sized
{
fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
}
//~^ ERROR E0038
//~| ERROR E0038
//~| ERROR E0277
- //~| WARNING E0038
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Type ascription is feature gated
+
+fn main() {
+ let a = 10: u8; //~ ERROR type ascription is experimental
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Operator precedence of type ascription
+// Type ascription has very high precedence, the same as operator `as`
+
+#![feature(type_ascription)]
+
+use std::ops::*;
+
+struct S;
+struct Z;
+
+impl Add<Z> for S {
+ type Output = S;
+ fn add(self, _rhs: Z) -> S { panic!() }
+}
+impl Mul<Z> for S {
+ type Output = S;
+ fn mul(self, _rhs: Z) -> S { panic!() }
+}
+impl Neg for S {
+ type Output = Z;
+ fn neg(self) -> Z { panic!() }
+}
+impl Deref for S {
+ type Target = Z;
+ fn deref(&self) -> &Z { panic!() }
+}
+
+fn main() {
+ &S: &S; // OK
+ (&S): &S; // OK
+ &(S: &S); //~ ERROR mismatched types
+
+ *S: Z; // OK
+ (*S): Z; // OK
+ *(S: Z); //~ ERROR mismatched types
+ //~^ ERROR type `Z` cannot be dereferenced
+
+ -S: Z; // OK
+ (-S): Z; // OK
+ -(S: Z); //~ ERROR mismatched types
+ //~^ ERROR cannot apply unary operator `-` to type `Z`
+
+ S + Z: Z; // OK
+ S + (Z: Z); // OK
+ (S + Z): Z; //~ ERROR mismatched types
+
+ S * Z: Z; // OK
+ S * (Z: Z); // OK
+ (S * Z): Z; //~ ERROR mismatched types
+
+ S .. S: S; // OK
+ S .. (S: S); // OK
+ (S .. S): S; //~ ERROR mismatched types
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Type ascription doesn't lead to unsoundness
+
+#![feature(type_ascription)]
+
+fn main() {
+ let arr = &[1u8, 2, 3];
+ let ref x = arr: &[u8]; //~ ERROR mismatched types
+ let ref mut x = arr: &[u8]; //~ ERROR mismatched types
+ match arr: &[u8] { //~ ERROR mismatched types
+ ref x => {}
+ }
+ let _len = (arr: &[u8]).len(); //~ ERROR mismatched types
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+
+// Test that when a `..` impl applies, we also check that any
+// supertrait conditions are met.
+
+#![feature(optin_builtin_traits)]
+
+trait NotImplemented { }
+
+trait MyTrait: Sized
+ where Option<Self> : NotImplemented
+{}
+
+impl NotImplemented for i32 {}
+
+impl MyTrait for .. {}
+
+fn bar<T:NotImplemented>() { }
+
+fn test() {
+ bar::<Option<i32>>();
+ //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
+}
+
+fn main() {
+}
trait NotImplemented { }
-trait MyTrait
+trait MyTrait: Sized
where Option<Self> : NotImplemented
{}
impl MyTrait for .. {}
fn foo<T:MyTrait>() {
- bar::<Option<T>>()
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<T>`
- //
// This should probably typecheck. This is #20671.
}
fn bar<T:NotImplemented>() { }
-fn test() {
- bar::<Option<i32>>();
- //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
-}
-
fn main() {
- foo::<u32>();
- //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<u32>`
}
}
fn get_min_from_max<'min, 'max, G>()
- where 'max : 'min, &'max G : Get
+ where 'max : 'min, &'max G : Get, G : 'max
{
impls_get::<&'min G>(); //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>()
- where 'max : 'min, &'min G : Get
+ where 'max : 'min, &'min G : Get, G : 'min
{
impls_get::<&'max G>(); //~ ERROR mismatched types
}
#![allow(dead_code)]
struct Foo {
- foo: [[u8]], //~ WARN E0277
+ foo: [[u8]], //~ ERROR E0277
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait ExtraCopy<T:Copy> { }
-enum SomeEnum<T,U> //~ WARN E0277
+enum SomeEnum<T,U> //~ ERROR E0277
where T: ExtraCopy<U>
{
SomeVariant(T,U)
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait ExtraCopy<T:Copy> { }
-fn foo<T,U>() where T: ExtraCopy<U> //~ WARN E0277
+fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
{
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
}
impl<'a, T> Foo<'a> for T {
- type Bar = &'a T; //~ WARN E0309
+ type Bar = &'a T; //~ ERROR E0309
}
#[rustc_error]
-fn main() { } //~ ERROR compilation
+fn main() { }
impl<T> Foo for T {
type Bar = MySet<T>;
- //~^ WARN the trait `MyHash` is not implemented for the type `T`
+ //~^ ERROR the trait `MyHash` is not implemented for the type `T`
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
struct Foo<T> {
// needs T: 'static
- x: fn() -> &'static T //~ WARN E0310
+ x: fn() -> &'static T //~ ERROR E0310
}
struct Bar<T> {
// needs T: Copy
- x: fn(&'static T) //~ WARN E0310
+ x: fn(&'static T) //~ ERROR E0310
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait MustBeCopy<T:Copy> {
}
-fn bar<T,U>() //~ WARN E0277
+fn bar<T,U>() //~ ERROR E0277
where T: MustBeCopy<U>
{
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
struct Foo<T> {
// needs T: 'static
- x: Object<&'static T> //~ WARN E0310
+ x: Object<&'static T> //~ ERROR E0310
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
struct Foo<T,U>(T,U);
impl<T,U> Foo<T,U> {
- fn foo(self) where T: ExtraCopy<U> //~ WARN E0277
+ fn foo(self) where T: ExtraCopy<U> //~ ERROR E0277
{}
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
struct Foo<T,U>(T,U);
-impl<T,U> Foo<T,U> where T: ExtraCopy<U> //~ WARN E0277
+impl<T,U> Foo<T,U> where T: ExtraCopy<U> //~ ERROR E0277
{
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
struct Foo<'a,T> {
f: &'a fn(T),
- //~^ WARN E0309
+ //~^ ERROR E0309
}
struct Bar<'a,T> {
f: &'a Trait<T>,
- //~^ WARN E0309
+ //~^ ERROR E0309
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait ExtraCopy<T:Copy> { }
-struct SomeStruct<T,U> //~ WARN E0277
+struct SomeStruct<T,U> //~ ERROR E0277
where T: ExtraCopy<U>
{
data: (T,U)
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait ExtraCopy<T:Copy> { }
-trait SomeTrait<T> { //~ WARN E0277
+trait SomeTrait<T> { //~ ERROR E0277
type Type1: ExtraCopy<T>;
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait SomeTrait<'a> {
type Type1;
type Type2 = &'a Self::Type1;
- //~^ WARN E0309
+ //~^ ERROR E0309
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait SomeTrait {
type Type1;
type Type2 = IsCopy<Self::Type1>;
- //~^ WARN E0277
+ //~^ ERROR E0277
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait ExtraCopy<T:Copy> { }
-trait SomeTrait<T,U> //~ WARN E0277
+trait SomeTrait<T,U> //~ ERROR E0277
where T: ExtraCopy<U>
{
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait Foo {
fn bar(&self, x: &Bar<Self>) {
- //~^ WARN E0277
+ //~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait Foo {
fn bar(&self) -> Bar<Self> {
- //~^ WARN E0277
+ //~^ ERROR E0277
//
// Here, Eq ought to be implemented.
loop { }
}
}
-#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait Foo {
fn bar<A>(&self) where A: Bar<Self> {
- //~^ WARN E0277
+ //~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait Foo {
fn bar(&self, x: &Bar<Self>);
- //~^ WARN E0277
+ //~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
-#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait Foo {
fn bar(&self) -> &Bar<Self>;
- //~^ WARN E0277
+ //~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
-#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait Foo {
fn bar(&self) where Bar<Self>: Copy;
- //~^ WARN E0277
+ //~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait ExtraCopy<T:Copy> { }
-trait SomeTrait<T>: ExtraCopy<T> { //~ WARN E0277
+trait SomeTrait<T>: ExtraCopy<T> { //~ ERROR E0277
}
-#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
fn main() {
for x in Foo {
- x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
+ x: 3 //~ ERROR expected type, found `3`
}.hi() {
println!("yo");
}
fn main() {
if Foo {
- x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
+ x: 3 //~ ERROR expected type, found `3`
}.hi() {
println!("yo");
}
fn main() {
while Foo {
- x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:`
+ x: 3 //~ ERROR expected type, found `3`
}.hi() {
println!("yo");
}
trait Chromosome<X: Chromosome<i32>> {
}
+impl Chromosome<i32> for i32 { }
+
fn main() { }
struct Struct<C:Chromosome> { c: C }
+impl Chromosome for i32 { }
+
+impl Get<Struct<i32>> for i32 {
+ fn get(&self) -> Struct<i32> {
+ Struct { c: *self }
+ }
+}
+
fn main() { }
println!("{:?}",y);
}
-trait Foo {
+trait Foo
+ where for<'a> &'a Self: Bar
+{
fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output;
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// ignore-pretty
+
+mod issue_26873_multifile;
+
+fn main() {}
+
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod A {
+ pub mod B {
+ use super::*;
+
+ pub struct S;
+ }
+
+ pub mod C {
+ use super::*;
+ use super::B::S;
+
+ pub struct T;
+ }
+
+ pub use self::C::T;
+}
+
+use A::*;
+
+fn main() {}
+
val.size_of_val()
}
-pub trait TypeInfo {
+pub trait TypeInfo: Sized {
fn size_of(_lame_type_hint: Option<Self>) -> usize;
fn size_of_val(&self) -> usize;
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::*;
+
+pub struct S;
+
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::*;
+
+use super::B::S;
+
+pub struct T { i: i32 }
+
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod B;
+pub mod C;
+
+pub use self::C::T;
+
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod A;
+
+use self::A::*;
+
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+#[rustc_mir]
+fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
+ // Test passing a number of arguments including a fat pointer.
+ // Also returning via an out pointer
+ fn callee(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
+ (a, b, c)
+ }
+ callee(a, b, c)
+}
+
+#[rustc_mir]
+fn test2(a: isize) -> isize {
+ // Test passing a single argument.
+ // Not using out pointer.
+ fn callee(a: isize) -> isize {
+ a
+ }
+ callee(a)
+}
+
+struct Foo;
+impl Foo {
+ fn inherent_method(&self, a: isize) -> isize { a }
+}
+
+#[rustc_mir]
+fn test3(x: &Foo, a: isize) -> isize {
+ // Test calling inherent method
+ x.inherent_method(a)
+}
+
+trait Bar {
+ fn extension_method(&self, a: isize) -> isize { a }
+}
+impl Bar for Foo {}
+
+#[rustc_mir]
+fn test4(x: &Foo, a: isize) -> isize {
+ // Test calling extension method
+ x.extension_method(a)
+}
+
+#[rustc_mir]
+fn test5(x: &Bar, a: isize) -> isize {
+ // Test calling method on trait object
+ x.extension_method(a)
+}
+
+#[rustc_mir]
+fn test6<T: Bar>(x: &T, a: isize) -> isize {
+ // Test calling extension method on generic callee
+ x.extension_method(a)
+}
+
+trait One<T = Self> {
+ fn one() -> T;
+}
+impl One for isize {
+ fn one() -> isize { 1 }
+}
+
+#[rustc_mir]
+fn test7() -> isize {
+ // Test calling trait static method
+ <isize as One>::one()
+}
+
+struct Two;
+impl Two {
+ fn two() -> isize { 2 }
+}
+
+#[rustc_mir]
+fn test8() -> isize {
+ // Test calling impl static method
+ Two::two()
+}
+
+fn main() {
+ assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..]));
+ assert_eq!(test2(98), 98);
+ assert_eq!(test3(&Foo, 42), 42);
+ assert_eq!(test4(&Foo, 970), 970);
+ assert_eq!(test5(&Foo, 8576), 8576);
+ assert_eq!(test6(&Foo, 12367), 12367);
+ assert_eq!(test7(), 1);
+ assert_eq!(test8(), 2);
+}
use std::ops::Deref;
-pub trait ToOwned {
+pub trait ToOwned: Sized {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
}
}
trait UseLife02 {
- fn refs<'a, T, H: HasType<&'a T>>(&'a self) -> H;
+ fn refs<'a, T: 'a, H: HasType<&'a T>>(&'a self) -> H;
}
trait UseLife03<T> {
- fn refs<'a, H: HasType<&'a T>>(&'a self) -> H;
+ fn refs<'a, H: HasType<&'a T>>(&'a self) -> H where T: 'a;
}
unimplemented!()
}
-pub fn top_refs_2<'a, T, H: HasType<&'a T>>(_s: &'a ()) -> H {
+pub fn top_refs_2<'a, T: 'a, H: HasType<&'a T>>(_s: &'a ()) -> H {
unimplemented!()
}
use std::cmp::PartialOrd;
-pub trait NumCast {
+pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}
// pretty-expanded FIXME #23616
-pub trait NumCast {
+pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait NumCast {
+pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}
// pretty-expanded FIXME #23616
-pub trait NumCast {
+pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}
fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool;
}
-trait Float: FuzzyEq<Self> {
+trait Float: Sized+FuzzyEq<Self> {
fn two_pi() -> Self;
}
fn f(&self, x: &T);
}
-trait Bar : Foo<Self> {
+trait Bar : Sized + Foo<Self> {
fn g(&self);
}
fn add(&self, rhs: &RHS) -> Result;
}
-trait MyNum : Add<Self,Self> { }
+trait MyNum : Sized + Add<Self,Self> { }
struct MyInt { val: isize }
fn add(&self, rhs: &RHS) -> Result;
}
-trait MyNum : Add<Self,Self> { }
+trait MyNum : Sized + Add<Self,Self> { }
struct MyInt { val: isize }
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Type ascription doesn't lead to unsoundness
+
+#![feature(type_ascription)]
+
+use std::mem;
+
+const C1: u8 = 10: u8;
+const C2: [u8; 1: usize] = [1];
+
+struct S {
+ a: u8
+}
+
+fn main() {
+ assert_eq!(C1.into(): i32, 10);
+ assert_eq!(C2[0], 1);
+
+ let s = S { a: 10: u8 };
+ let arr = &[1u8, 2, 3];
+
+ let mut v = arr.iter().cloned().collect(): Vec<_>;
+ v.push(4);
+ assert_eq!(v, [1, 2, 3, 4]);
+
+ let a = 1: u8;
+ let b = a.into(): u16;
+ assert_eq!(v[a.into(): usize], 2);
+ assert_eq!(mem::size_of_val(&a), 1);
+ assert_eq!(mem::size_of_val(&b), 2);
+ assert_eq!(b, 1: u16);
+
+ let mut v = Vec::new();
+ v: Vec<u8> = vec![1, 2, 3]; // Lvalue type ascription
+ assert_eq!(v, [1u8, 2, 3]);
+}
trait T4<X> {
fn dummy(&self) { }
- fn m1(x: &T4<X>, y: X);
- fn m2(x: &T5<X>, y: X);
+ fn m1(&self, x: &T4<X>, y: X);
+ fn m2(&self, x: &T5<X>, y: X);
}
trait T5<X: ?Sized> {
fn dummy(&self) { }
// not an error (for now)
- fn m1(x: &T4<X>);
- fn m2(x: &T5<X>);
+ fn m1(&self, x: &T4<X>);
+ fn m2(&self, x: &T5<X>);
}
trait T6<X: T> {
fn dummy(&self) { }
- fn m1(x: &T4<X>);
- fn m2(x: &T5<X>);
+ fn m1(&self, x: &T4<X>);
+ fn m2(&self, x: &T5<X>);
}
trait T7<X: ?Sized+T> {
fn dummy(&self) { }
// not an error (for now)
- fn m1(x: &T4<X>);
- fn m2(x: &T5<X>);
+ fn m1(&self, x: &T4<X>);
+ fn m2(&self, x: &T5<X>);
}
// The last field in a struct or variant may be unsized