Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected compiler panic #19734

Closed
th0114nd opened this issue Dec 11, 2014 · 3 comments · Fixed by #19778
Closed

Unexpected compiler panic #19734

th0114nd opened this issue Dec 11, 2014 · 3 comments · Fixed by #19778
Labels
I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️

Comments

@th0114nd
Copy link
Contributor

The version of rust I was using was

rustc 0.13.0-nightly (8bca470c5 2014-12-08 00:12:30 +0000)
binary: rustc
commit-hash: 8bca470c5acf13aa20022a2c462a89f72de721fc
commit-date: 2014-12-08 00:12:30 +0000
host: x86_64-apple-darwin
release: 0.13.0-nightly

The file I was compiling was

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::ascii::AsciiExt;

use dom::attr::Attr;
use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding;
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding::HTMLScriptElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived, HTMLScriptElementCast};
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{HTMLScriptElementTypeId, Element, AttributeHandlers};
use dom::element::{ElementCreator, ParserCreated};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, NodeHelpers, ElementNodeTypeId, window_from_node, CloneChildrenFlag};
use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;

use encoding::all::UTF_8;
use encoding::types::{Encoding, DecodeReplace};
use servo_net::resource_task::load_whole_resource;
use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec};
use std::cell::Cell;
use string_cache::Atom;
use url::UrlParser;

#[dom_struct]
pub struct HTMLScriptElement {
    htmlelement: HTMLElement,

    /// https://html.spec.whatwg.org/multipage/scripting.html#already-started
    already_started: Cell<bool>,

    /// https://html.spec.whatwg.org/multipage/scripting.html#parser-inserted
    parser_inserted: Cell<bool>,

    /// https://html.spec.whatwg.org/multipage/scripting.html#non-blocking
    ///
    /// (currently unused)
    non_blocking: Cell<bool>,

    /// https://html.spec.whatwg.org/multipage/scripting.html#ready-to-be-parser-executed
    ///
    /// (currently unused)
    ready_to_be_parser_executed: Cell<bool>,
}

impl HTMLScriptElementDerived for EventTarget {
    fn is_htmlscriptelement(&self) -> bool {
        *self.type_id() == NodeTargetTypeId(ElementNodeTypeId(HTMLScriptElementTypeId))
    }
}

impl HTMLScriptElement {
    fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>,
                     creator: ElementCreator) -> HTMLScriptElement {
        HTMLScriptElement {
            htmlelement: HTMLElement::new_inherited(HTMLScriptElementTypeId, localName, prefix, document),
            already_started: Cell::new(false),
            parser_inserted: Cell::new(creator == ParserCreated),
            non_blocking: Cell::new(creator != ParserCreated),
            ready_to_be_parser_executed: Cell::new(false),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>,
               creator: ElementCreator) -> Temporary<HTMLScriptElement> {
        let element = HTMLScriptElement::new_inherited(localName, prefix, document, creator);
        Node::reflect_node(box element, document, HTMLScriptElementBinding::Wrap)
    }
}

pub trait HTMLScriptElementHelpers {
    /// Prepare a script (<http://www.whatwg.org/html/#prepare-a-script>)
    fn prepare(self);

    /// Prepare a script, steps 6 and 7.
    fn is_javascript(self) -> bool;

    /// Set the "already started" flag (<https://whatwg.org/html/#already-started>)
    fn mark_already_started(self);
}

/// Supported script types as defined by
/// <http://whatwg.org/html/#support-the-scripting-language>.
static SCRIPT_JS_MIMES: StaticStringVec = &[
    "application/ecmascript",
    "application/javascript",
    "application/x-ecmascript",
    "application/x-javascript",
    "text/ecmascript",
    "text/javascript",
    "text/javascript1.0",
    "text/javascript1.1",
    "text/javascript1.2",
    "text/javascript1.3",
    "text/javascript1.4",
    "text/javascript1.5",
    "text/jscript",
    "text/livescript",
    "text/x-ecmascript",
    "text/x-javascript",
];

impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
    fn prepare(self) {
        // https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script
        // Step 1.
        if self.already_started.get() {
            return;
        }
        // Step 2.
        let was_parser_inserted = self.parser_inserted.get();
        self.parser_inserted.set(false);

        // Step 3.
        let element: JSRef<Element> = ElementCast::from_ref(self);
        if was_parser_inserted && element.has_attribute(&atom!("async")) {
            self.non_blocking.set(true);
        }
        // Step 4.
        let text = self.Text();
        if text.len() == 0 && !element.has_attribute(&atom!("src")) {
            return;
        }
        // Step 5.
        let node: JSRef<Node> = NodeCast::from_ref(self);
        if !node.is_in_doc() {
            return;
        }
        // Step 6, 7.
        if !self.is_javascript() {
            return;
        }
        // Step 8.
        if was_parser_inserted {
            self.parser_inserted.set(true);
            self.non_blocking.set(false);
        }
        // Step 9.
        self.already_started.set(true);

        // Step 10.
        // TODO: If the element is flagged as "parser-inserted", but the element's node document is
        // not the Document of the parser that created the element, then abort these steps.
        if self.parser_inserted.get() && document.from_root(node) != self. 

        // Step 11.
        // TODO: If scripting is disabled for the script element, then the user agent must abort
        // these steps at this point. The script is not executed.

        // Step 12.
        // TODO: If the script element has an `event` attribute and a `for` attribute, then run
        // these substeps...
        if (element.has_attribute(&atom!("event")) && element.has_attribute(&atom!("for"))) {
            event_attr = element.get_string_attribute(&atom!("event")).trim().to_ascii_lower();
            if event_attr != "window" {
                return
            }
            for_attr = element.get_string_attribute(&atom!("for")).trim().to_ascii_lower();
            if for_attr != "onload" && for_attr != "onload()" {
                return
            }

        }

        // Step 13.
        // TODO: If the script element has a `charset` attribute, then let the script block's
        // character encoding for this script element be the result of getting an encoding from the
        // value of the `charset` attribute.

        // Step 14 and 15.
        // TODO: Add support for the `defer` and `async` attributes.  (For now, we fetch all
        // scripts synchronously and execute them immediately.)
        let window = window_from_node(self).root();
        let page = window.page();
        let base_url = page.get_url();

        let (source, url) = match element.get_attribute(ns!(""), &atom!("src")).root() {
            Some(src) => {
                if src.deref().Value().is_empty() {
                    // TODO: queue a task to fire a simple event named `error` at the element
                    return;
                }
                match UrlParser::new().base_url(&base_url).parse(src.deref().Value().as_slice()) {
                    Ok(url) => {
                        // TODO: Do a potentially CORS-enabled fetch with the mode being the current
                        // state of the element's `crossorigin` content attribute, the origin being
                        // the origin of the script element's node document, and the default origin
                        // behaviour set to taint.
                        match load_whole_resource(&page.resource_task, url) {
                            Ok((metadata, bytes)) => {
                                // TODO: use the charset from step 13.
                                let source = UTF_8.decode(bytes.as_slice(), DecodeReplace).unwrap();
                                (source, metadata.final_url)
                            }
                            Err(_) => {
                                error!("error loading script {}", src.deref().Value());
                                return;
                            }
                        }
                    }
                    Err(_) => {
                        // TODO: queue a task to fire a simple event named `error` at the element
                        error!("error parsing URL for script {}", src.deref().Value());
                        return;
                    }
                }
            }
            None => (text, base_url)
        };

        window.evaluate_script_with_result(source.as_slice(), url.serialize().as_slice());
    }

    fn is_javascript(self) -> bool {
        let element: JSRef<Element> = ElementCast::from_ref(self);
        match element.get_attribute(ns!(""), &atom!("type")).root().map(|s| s.Value()) {
            Some(ref s) if s.is_empty() => {
                // type attr exists, but empty means js
                debug!("script type empty, inferring js");
                true
            },
            Some(ref s) => {
                debug!("script type={:s}", *s);
                SCRIPT_JS_MIMES.contains(&s.to_ascii_lower().as_slice().trim_chars(HTML_SPACE_CHARACTERS))
            },
            None => {
                debug!("no script type");
                match element.get_attribute(ns!(""), &atom!("language"))
                             .root()
                             .map(|s| s.Value()) {
                    Some(ref s) if s.is_empty() => {
                        debug!("script language empty, inferring js");
                        true
                    },
                    Some(ref s) => {
                        debug!("script language={:s}", *s);
                        SCRIPT_JS_MIMES.contains(&format!("text/{}", s).to_ascii_lower().as_slice())
                    },
                    None => {
                        debug!("no script type or language, inferring js");
                        true
                    }
                }
            }
        }
    }

    fn mark_already_started(self) {
        self.already_started.set(true);
    }
}

impl<'a> VirtualMethods for JSRef<'a, HTMLScriptElement> {
    fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
        let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
        Some(htmlelement as &VirtualMethods)
    }

    fn after_set_attr(&self, attr: JSRef<Attr>) {
        match self.super_type() {
            Some(ref s) => s.after_set_attr(attr),
            _ => (),
        }
        let node: JSRef<Node> = NodeCast::from_ref(*self);
        if attr.local_name() == &atom!("src") && !self.parser_inserted.get() && node.is_in_doc() {
            self.prepare();
        }
    }

    fn child_inserted(&self, child: JSRef<Node>) {
        match self.super_type() {
            Some(ref s) => s.child_inserted(child),
            _ => (),
        }
        let node: JSRef<Node> = NodeCast::from_ref(*self);
        if !self.parser_inserted.get() && node.is_in_doc() {
            self.prepare();
        }
    }

    fn bind_to_tree(&self, tree_in_doc: bool) {
        match self.super_type() {
            Some(ref s) => s.bind_to_tree(tree_in_doc),
            _ => ()
        }

        if tree_in_doc && !self.parser_inserted.get() {
            self.prepare();
        }
    }

    fn cloning_steps(&self, copy: JSRef<Node>, maybe_doc: Option<JSRef<Document>>,
                     clone_children: CloneChildrenFlag) {
        match self.super_type() {
            Some(ref s) => s.cloning_steps(copy, maybe_doc, clone_children),
            _ => (),
        }

        // https://whatwg.org/html/#already-started
        if self.already_started.get() {
            let copy_elem: JSRef<HTMLScriptElement> = HTMLScriptElementCast::to_ref(copy).unwrap();
            copy_elem.mark_already_started();
        }
    }
}

impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> {
    make_url_getter!(Src)

    make_setter!(SetSrc, "src")

    // http://www.whatwg.org/html/#dom-script-text
    fn Text(self) -> DOMString {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        Node::collect_text_contents(node.children())
    }

    // http://www.whatwg.org/html/#dom-script-text
    fn SetText(self, value: DOMString) {
        let node: JSRef<Node> = NodeCast::from_ref(self);
        node.SetTextContent(Some(value))
    }
}

impl Reflectable for HTMLScriptElement {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.htmlelement.reflector()
    }
}

The error reported was

htmlscriptelement.rs:126:58: 126:62 error: macro undefined: 'atom!'
htmlscriptelement.rs:126         if was_parser_inserted && element.has_attribute(&atom!("async")) {
                                                                                  ^~~~
htmlscriptelement.rs:131:55: 131:59 error: macro undefined: 'atom!'
htmlscriptelement.rs:131         if text.len() == 0 && !element.has_attribute(&atom!("src")) {
                                                                               ^~~~
htmlscriptelement.rs:163:36: 163:40 error: macro undefined: 'atom!'
htmlscriptelement.rs:163         if (element.has_attribute(&atom!("event")) && element.has_attribute(&atom!("for"))) {
                                                            ^~~~
htmlscriptelement.rs:163:78: 163:82 error: macro undefined: 'atom!'
htmlscriptelement.rs:163         if (element.has_attribute(&atom!("event")) && element.has_attribute(&atom!("for"))) {
                                                                                                      ^~~~
htmlscriptelement.rs:164:56: 164:60 error: macro undefined: 'atom!'
htmlscriptelement.rs:164             event_attr = element.get_string_attribute(&atom!("event")).trim().to_ascii_lower();
                                                                                ^~~~
htmlscriptelement.rs:168:54: 168:58 error: macro undefined: 'atom!'
htmlscriptelement.rs:168             for_attr = element.get_string_attribute(&atom!("for")).trim().to_ascii_lower();
                                                                              ^~~~
htmlscriptelement.rs:187:57: 187:59 error: macro undefined: 'ns!'
htmlscriptelement.rs:187         let (source, url) = match element.get_attribute(ns!(""), &atom!("src")).root() {
                                                                                 ^~
htmlscriptelement.rs:187:67: 187:71 error: macro undefined: 'atom!'
htmlscriptelement.rs:187         let (source, url) = match element.get_attribute(ns!(""), &atom!("src")).root() {
                                                                                           ^~~~
htmlscriptelement.rs:206:33: 206:38 error: macro undefined: 'error!'
htmlscriptelement.rs:206                                 error!("error loading script {}", src.deref().Value());
                                                         ^~~~~
htmlscriptelement.rs:213:25: 213:30 error: macro undefined: 'error!'
htmlscriptelement.rs:213                         error!("error parsing URL for script {}", src.deref().Value());
                                                 ^~~~~
htmlscriptelement.rs:226:37: 226:39 error: macro undefined: 'ns!'
htmlscriptelement.rs:226         match element.get_attribute(ns!(""), &atom!("type")).root().map(|s| s.Value()) {
                                                             ^~
htmlscriptelement.rs:226:47: 226:51 error: macro undefined: 'atom!'
htmlscriptelement.rs:226         match element.get_attribute(ns!(""), &atom!("type")).root().map(|s| s.Value()) {
                                                                       ^~~~
htmlscriptelement.rs:229:17: 229:22 error: macro undefined: 'debug!'
htmlscriptelement.rs:229                 debug!("script type empty, inferring js");
                                         ^~~~~
htmlscriptelement.rs:233:17: 233:22 error: macro undefined: 'debug!'
htmlscriptelement.rs:233                 debug!("script type={:s}", *s);
                                         ^~~~~
htmlscriptelement.rs:237:17: 237:22 error: macro undefined: 'debug!'
htmlscriptelement.rs:237                 debug!("no script type");
                                         ^~~~~
htmlscriptelement.rs:238:45: 238:47 error: macro undefined: 'ns!'
htmlscriptelement.rs:238                 match element.get_attribute(ns!(""), &atom!("language"))
                                                                     ^~
htmlscriptelement.rs:238:55: 238:59 error: macro undefined: 'atom!'
htmlscriptelement.rs:238                 match element.get_attribute(ns!(""), &atom!("language"))
                                                                               ^~~~
htmlscriptelement.rs:242:25: 242:30 error: macro undefined: 'debug!'
htmlscriptelement.rs:242                         debug!("script language empty, inferring js");
                                                 ^~~~~
htmlscriptelement.rs:246:25: 246:30 error: macro undefined: 'debug!'
htmlscriptelement.rs:246                         debug!("script language={:s}", *s);
                                                 ^~~~~
htmlscriptelement.rs:250:25: 250:30 error: macro undefined: 'debug!'
htmlscriptelement.rs:250                         debug!("no script type or language, inferring js");
                                                 ^~~~~
htmlscriptelement.rs:275:34: 275:38 error: macro undefined: 'atom!'
htmlscriptelement.rs:275         if attr.local_name() == &atom!("src") && !self.parser_inserted.get() && node.is_in_doc() {
                                                          ^~~~
htmlscriptelement.rs:318:5: 318:20 error: macro undefined: 'make_url_getter!'
htmlscriptelement.rs:318     make_url_getter!(Src)
                             ^~~~~~~~~~~~~~~
error: internal compiler error: tried to pop without a push
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html
note: run with `RUST_BACKTRACE=1` for a backtrace

And the backtrace was

task 'rustc' panicked at 'Box<Any>', /Users/rustbuild/src/rust-buildbot/slave/nightly-mac/build/src/libsyntax/diagnostic.rs:180

stack backtrace:
   1:        0x10f854380 - rt::backtrace::imp::write::hbe4d08f138d707c0Lsy
   2:        0x10f857590 - failure::on_fail::h868d2af5cb92d796nQy
   3:        0x10faaa9f5 - unwind::begin_unwind_inner::h8e9132cd5161ca28lJc
   4:        0x10f0128d7 - unwind::begin_unwind::h7562983727733833076
   5:        0x10f01328f - diagnostic::Handler::bug::hdce737e54ea4c046ubG
   6:        0x10f0efad8 - ext::base::ExtCtxt<'a>::bug::h7311b9eddc579b283r8
   7:        0x10f0b943e - ext::base::ExtCtxt<'a>::bt_pop::h70ba23420105c926mo8
   8:        0x10f1575b9 - ext::expand::MacroExpander<'a, 'b>.Folder::fold_method::h4d254140b60e7bf9qRf
   9:        0x10f151336 - ext::expand::MacroExpander<'a, 'b>.Folder::fold_item_underscore::h0d0ee757905cce1c6Pf
  10:        0x10f14f3d4 - fold::noop_fold_item::closure.54564
  11:        0x10f0023df - ptr::P<T>::map::h5441013841086107152
  12:        0x10f14b341 - ext::expand::expand_item::h1b2b3e29ee635969x4e
  13:        0x10f155527 - fold::noop_fold_mod::closure.54593
  14:        0x10f001b7f - iter::IteratorExt::collect::h17670113594715964984
  15:        0x10f150152 - ext::expand::MacroExpander<'a, 'b>.Folder::fold_item_underscore::h0d0ee757905cce1c6Pf
  16:        0x10f14f3d4 - fold::noop_fold_item::closure.54564
  17:        0x10f0023df - ptr::P<T>::map::h5441013841086107152
  18:        0x10f14b034 - ext::expand::expand_item::h1b2b3e29ee635969x4e
  19:        0x10f191f45 - ext::expand::expand_crate::hea92d1a095b00bf1cTf
  20:        0x10c24f6e2 - driver::phase_2_configure_and_expand::closure.16967
  21:        0x10c20c84f - driver::phase_2_configure_and_expand::he62365fef9b99479Qha
  22:        0x10c1ff67f - driver::compile_input::h9621f58ee716cb79pba
  23:        0x10c29720d - run_compiler::h6d3de3a676f705b7z4b
  24:        0x10c295c6e - run::closure.21247
  25:        0x10c2a70ce - task::TaskBuilder::try_future::closure.22695
  26:        0x10f82d713 - task::TaskBuilder::spawn_internal::closure.31212
  27:        0x10faa859d - task::Task::spawn::closure.5610
  28:        0x10fb1210c - rust_try_inner
  29:        0x10fb120f6 - rust_try
  30:        0x10faa8677 - unwind::try::h0dc7caf9a65e998fExc
  31:        0x10faa844c - task::Task::run::h986874b42196d947rMb
  32:        0x10faa814f - task::Task::spawn::closure.5586
  33:        0x10faa9a57 - thread::thread_start::hd43c648d26329b09u4b
  34:     0x7fff8dbc82fc - _pthread_body
  35:     0x7fff8dbc8279 - _pthread_body
@steveklabnik steveklabnik added the I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ label Dec 11, 2014
@th0114nd
Copy link
Contributor Author

I was able to reduce the input file significantly:

impl Trait for Type {
    undef_macro!()
}

@bstrie
Copy link
Contributor

bstrie commented Dec 12, 2014

impl Foo { bar!() } does it as well.

@aochagavia
Copy link
Contributor

I think I have a fix for this. Compiling rustc right now.

brson added a commit to brson/rust that referenced this issue Dec 12, 2014
brson added a commit to brson/rust that referenced this issue Dec 13, 2014
bors added a commit that referenced this issue Dec 14, 2014
Fix #19734

Reviewed-by: alexcrichton
bors referenced this issue Dec 14, 2014
This line was declared twice, which causes the build of i10n docs to
fail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants