allow inherent implementations on primitives
This commit is contained in:
parent
92dd995e17
commit
8570739880
@ -239,6 +239,24 @@ pub fn collect_language_items(krate: &ast::Crate,
|
||||
|
||||
lets_do_this! {
|
||||
// Variant name, Name, Method name;
|
||||
CharImplItem, "char", char_impl;
|
||||
StrImplItem, "str", str_impl;
|
||||
SliceImplItem, "slice", slice_impl;
|
||||
ConstPtrImplItem, "const_ptr", const_ptr_impl;
|
||||
MutPtrImplItem, "mut_ptr", mut_ptr_impl;
|
||||
I8ImplItem, "i8", i8_impl;
|
||||
I16ImplItem, "i16", i16_impl;
|
||||
I32ImplItem, "i32", i32_impl;
|
||||
I64ImplItem, "i64", i64_impl;
|
||||
IsizeImplItem, "isize", isize_impl;
|
||||
U8ImplItem, "u8", u8_impl;
|
||||
U16ImplItem, "u16", u16_impl;
|
||||
U32ImplItem, "u32", u32_impl;
|
||||
U64ImplItem, "u64", u64_impl;
|
||||
UsizeImplItem, "usize", usize_impl;
|
||||
F32ImplItem, "f32", f32_impl;
|
||||
F64ImplItem, "f64", f64_impl;
|
||||
|
||||
SendTraitLangItem, "send", send_trait;
|
||||
SizedTraitLangItem, "sized", sized_trait;
|
||||
CopyTraitLangItem, "copy", copy_trait;
|
||||
|
@ -788,6 +788,9 @@ pub struct ctxt<'tcx> {
|
||||
/// is used for lazy resolution of traits.
|
||||
pub populated_external_traits: RefCell<DefIdSet>,
|
||||
|
||||
/// The set of external primitive inherent implementations that have been read.
|
||||
pub populated_external_primitive_impls: RefCell<DefIdSet>,
|
||||
|
||||
/// Borrows
|
||||
pub upvar_capture_map: RefCell<UpvarCaptureMap>,
|
||||
|
||||
@ -2599,6 +2602,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||
used_mut_nodes: RefCell::new(NodeSet()),
|
||||
populated_external_types: RefCell::new(DefIdSet()),
|
||||
populated_external_traits: RefCell::new(DefIdSet()),
|
||||
populated_external_primitive_impls: RefCell::new(DefIdSet()),
|
||||
upvar_capture_map: RefCell::new(FnvHashMap()),
|
||||
extern_const_statics: RefCell::new(DefIdMap()),
|
||||
extern_const_variants: RefCell::new(DefIdMap()),
|
||||
@ -5988,6 +5992,25 @@ pub fn record_trait_implementation(tcx: &ctxt,
|
||||
tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
|
||||
}
|
||||
|
||||
/// Load primitive inherent implementations if necessary
|
||||
pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt, lang_def_id: ast::DefId) {
|
||||
if lang_def_id.krate == LOCAL_CRATE {
|
||||
return
|
||||
}
|
||||
if tcx.populated_external_primitive_impls.borrow().contains(&lang_def_id) {
|
||||
return
|
||||
}
|
||||
|
||||
debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", lang_def_id);
|
||||
|
||||
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, lang_def_id);
|
||||
|
||||
// Store the implementation info.
|
||||
tcx.impl_items.borrow_mut().insert(lang_def_id, impl_items);
|
||||
|
||||
tcx.populated_external_primitive_impls.borrow_mut().insert(lang_def_id);
|
||||
}
|
||||
|
||||
/// Populates the type context with all the implementations for the given type
|
||||
/// if necessary.
|
||||
pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
|
||||
|
@ -289,11 +289,87 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
ty::ty_param(p) => {
|
||||
self.assemble_inherent_candidates_from_param(self_ty, p);
|
||||
}
|
||||
ty::ty_char => {
|
||||
let lang_def_id = self.tcx().lang_items.char_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_str => {
|
||||
let lang_def_id = self.tcx().lang_items.str_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_vec(_, None) => {
|
||||
let lang_def_id = self.tcx().lang_items.slice_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => {
|
||||
let lang_def_id = self.tcx().lang_items.const_ptr_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => {
|
||||
let lang_def_id = self.tcx().lang_items.mut_ptr_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_int(ast::TyI8) => {
|
||||
let lang_def_id = self.tcx().lang_items.i8_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_int(ast::TyI16) => {
|
||||
let lang_def_id = self.tcx().lang_items.i16_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_int(ast::TyI32) => {
|
||||
let lang_def_id = self.tcx().lang_items.i32_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_int(ast::TyI64) => {
|
||||
let lang_def_id = self.tcx().lang_items.i64_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_int(ast::TyIs(_)) => {
|
||||
let lang_def_id = self.tcx().lang_items.isize_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_uint(ast::TyU8) => {
|
||||
let lang_def_id = self.tcx().lang_items.u8_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_uint(ast::TyU16) => {
|
||||
let lang_def_id = self.tcx().lang_items.u16_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_uint(ast::TyU32) => {
|
||||
let lang_def_id = self.tcx().lang_items.u32_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_uint(ast::TyU64) => {
|
||||
let lang_def_id = self.tcx().lang_items.u64_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_uint(ast::TyUs(_)) => {
|
||||
let lang_def_id = self.tcx().lang_items.usize_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_float(ast::TyF32) => {
|
||||
let lang_def_id = self.tcx().lang_items.f32_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
ty::ty_float(ast::TyF64) => {
|
||||
let lang_def_id = self.tcx().lang_items.f64_impl();
|
||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<ast::DefId>) {
|
||||
if let Some(impl_def_id) = lang_def_id {
|
||||
ty::populate_implementations_for_primitive_if_necessary(self.tcx(), impl_def_id);
|
||||
|
||||
self.assemble_inherent_impl_probe(impl_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) {
|
||||
// Read the inherent implementation candidates for this type from the
|
||||
// metadata if necessary.
|
||||
|
@ -16,6 +16,7 @@ use middle::ty;
|
||||
use syntax::ast::{Item, ItemImpl};
|
||||
use syntax::ast;
|
||||
use syntax::ast_util;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::visit;
|
||||
use util::ppaux::{Repr, UserString};
|
||||
|
||||
@ -38,6 +39,23 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_primitive_impl(&self,
|
||||
impl_def_id: ast::DefId,
|
||||
lang_def_id: Option<ast::DefId>,
|
||||
lang: &str,
|
||||
ty: &str,
|
||||
span: Span) {
|
||||
match lang_def_id {
|
||||
Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ },
|
||||
_ => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
&format!("only a single inherent implementation marked with `#[lang = \"{}\"]` \
|
||||
is allowed for the `{}` primitive", lang, ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks exactly one impl for orphan rules and other such
|
||||
/// restrictions. In this fn, it can happen that multiple errors
|
||||
/// apply to a specific impl, so just return after reporting one
|
||||
@ -62,6 +80,125 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||
ty::ty_uniq(..) => {
|
||||
self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap());
|
||||
}
|
||||
ty::ty_char => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.char_impl(),
|
||||
"char",
|
||||
"char",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_str => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.str_impl(),
|
||||
"str",
|
||||
"str",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_vec(_, None) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.slice_impl(),
|
||||
"slice",
|
||||
"[T]",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.const_ptr_impl(),
|
||||
"const_ptr",
|
||||
"*const T",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.mut_ptr_impl(),
|
||||
"mut_ptr",
|
||||
"*mut T",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_int(ast::TyI8) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.i8_impl(),
|
||||
"i8",
|
||||
"i8",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_int(ast::TyI16) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.i16_impl(),
|
||||
"i16",
|
||||
"i16",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_int(ast::TyI32) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.i32_impl(),
|
||||
"i32",
|
||||
"i32",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_int(ast::TyI64) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.i64_impl(),
|
||||
"i64",
|
||||
"i64",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_int(ast::TyIs(_)) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.isize_impl(),
|
||||
"isize",
|
||||
"isize",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_uint(ast::TyU8) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.u8_impl(),
|
||||
"u8",
|
||||
"u8",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_uint(ast::TyU16) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.u16_impl(),
|
||||
"u16",
|
||||
"u16",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_uint(ast::TyU32) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.u32_impl(),
|
||||
"u32",
|
||||
"u32",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_uint(ast::TyU64) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.u64_impl(),
|
||||
"u64",
|
||||
"u64",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_uint(ast::TyUs(_)) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.usize_impl(),
|
||||
"usize",
|
||||
"usize",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_float(ast::TyF32) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.f32_impl(),
|
||||
"f32",
|
||||
"f32",
|
||||
item.span);
|
||||
}
|
||||
ty::ty_float(ast::TyF64) => {
|
||||
self.check_primitive_impl(def_id,
|
||||
self.tcx.lang_items.f64_impl(),
|
||||
"f64",
|
||||
"f64",
|
||||
item.span);
|
||||
}
|
||||
_ => {
|
||||
span_err!(self.tcx.sess, item.span, E0118,
|
||||
"no base type found for inherent implementation; \
|
||||
|
24
src/test/compile-fail/single-primitive-inherent-impl.rs
Normal file
24
src/test/compile-fail/single-primitive-inherent-impl.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// 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
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(lang_items)]
|
||||
#![feature(no_std)]
|
||||
#![no_std]
|
||||
|
||||
// OK
|
||||
#[lang = "char"]
|
||||
impl char {}
|
||||
|
||||
impl char {
|
||||
//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user